反射机制(四)操作方法

获取方法:

Class类中常用方法:
public Method[] getMethods();
-获取自身和继承过来的所有的public方法;

public Method[] getDeclaredMethods();
-获取自身所有的方法(不包括继承的,和访问权限无关)

public Method getMethod(String methodName,Class... parameterTypes);
-表示调用指定的一个public的方法(包括继承的);
-参数:methodName,表示被调用方法的名字;
            parameterTypes,表示被调用方法的参数的Class类型,如:String.class;

public Method getDeclaredMethod(String methodName,Class... parameterTypes);
-表示调用指定的一个本来中的方法(不包括继承的);

调用方法

在Method类中
public Object invoke(Object obj, Object... args);
-表示调用当前Method所表示的方法。

参数:
    obj:表示被调用方法底层所属对象;

Method m = clz.getMethod("sayHello",String.class);

args:表示调用方法时传递的实际参数;

返回:底层方法的返回结果。

*调用私有方法:
在调用私有方法之前应该何设置该方法为可访问的,又因为Method是AccessibleObject子类,所以Method类中具有该方法。    


问题一答案:

Object obj = new java.util.Date();
Method method = obj.getClass().getMethod("toLocalString",String.class);

Object date = method.invoke(obj);

使用反射调用可变参数

使用反射调用静态方法:

静态方法不属于任何对象,属于类本身。

调用静态方法:

-把invoke()方法的第一个参数设置为null即可;

例如:
   public class UseStaticMethod{
        public static void main(String[] args){
            Class clzz = User.class;
            Method m    
            =clzz.getMethod("doWork",String.class);
            m.invoke(null,"无关风月");
        }
    }
   class User{
            public static void doWork(String name){
        System.out.println("doWork(String name)被调用了"+"name = "+name);
            }
    }

设置为null处也可以设为方法所在类的对象,但其底层还是使用类调用,因此在运行时会被忽略该参数项,也就是说设置为任意对象都是可以运行成功的。

使用反射调用数组参数(可变参数):

-可变参数其底层就是一个数组。

使用反射调用方法的终极王道:

-调用方法时把实际参数统统作为Object[]的元素即可;


//使用反射调用可变参数(数组参数)
public class ArrayListArgs {
    public static void main(String[] args) throws Exception {
        Class clazz = Employee.class;
//        情况一:数组的元素类型是基本类型
        Method method = clazz.getMethod("doWork1", int[].class);
        System.out.println(method);
//        method.invoke(null,1,2,3,4,5,6);  ERROR
        method.invoke(null,new int[]{1,2,3,4,5});

        //        情况二:数组的元素类型是引用类型
        method = clazz.getMethod("doWork2", String[].class);
        System.out.println(method);
//        method.invoke(null,new String[]{"A","B","C"}); //ERROR


        method.invoke(null,new Object[]{new String[]{"A","B","C"}});
//      对于引用类型会被自动解包,因此我们在传值是就得反向对其装包,使用Object[]封装一层;也适用于基本类型;

//        对于参数列表是泛型的如何调用
        method = clazz.getMethod("toArray", Object[].class);
        System.out.println(method);
    }
}
class Employee{
    public static void doWork1(int... args){//等价于int[] args
        System.out.println("doWork1调用成功"+ Arrays.toString(args));
        //System.out.println("可变参数调用成功"+ args);  --打印的会是args的hashCode值;
    }

    public static void doWork2(String... args){//等价于int[] args
        System.out.println("doWork2调用成功"+ Arrays.toString(args));
    }

    public  T[] toArray(T[] a) {
        return null;
    }
}

其他API

//反射其他相关API
public abstract class OtherApi {
    public static void main(String[] args) {
//        获取修饰符
        Class clzz = OtherApi.class;
        int mod = clzz.getModifiers();//返回类型为int?查看Modifier类中定义,十分巧妙的设计;
        System.out.println(mod);
        String s = Modifier.toString(mod);
        System.out.println(s);

//        获取类名
        System.out.println(clzz.getName());//com.reflection._2_methods.OtherApi
        System.out.println(clzz.getSimpleName());//OtherApi

//        获取包名
        System.out.println(clzz.getPackage());//package com.reflection._2_methods
        System.out.println(clzz.getPackage().getName());//com.reflection._2_methods

//        获取父类名称
        System.out.println(clzz.getSuperclass());//class java.lang.Object
        System.out.println(clzz.getSuperclass().getName());//java.lang.Object

    }
}
//对于枚举类,无法使用反射获取其信息,因为枚举类没有构造器;
enum Gender{
     MAN,WOMAN,NONE;
}

你可能感兴趣的:(反射机制(四)操作方法)