技术交流


JAVA——反射

Mar 31, 2019 4:41:34 PM
226
2

反射

能够分析类能力的程序成为反射。

Class

每一个类是Class类的实例对象。

获取类类型的方法

类名.class == 实例对象.getClass() == Class.forName(类路径)

当一个类存在无参构造器可以获取类类型,使用“类类型.newInstance()”实例该类对象。

基本数据类型

像基本诗句类型intvoid关键字都有自己的类类型。

动态加载

反射可以实现动态加载类(程序运行时加载类)。

通过API获取类信息

获取类方法信息

/**
 * 打印类信息
 * @param object 对象
 */
public static void printClassInfo(Object object){
    //先要获取类类型
    Class classType = object.getClass();

    //getName()包含类路径获取类名称,getSimpleName()获取不包含类路径的的方法名
    System.out.println("类名:" + classType.getName());

    /**
     * getMethods():获取所有public方法信息,包括从父类继承而来的
     * getDeclaredMethods():获取该类自声明的方法,不论访问权限。
     */
    System.out.println("方法:");
    Method[] methods = classType.getMethods();
    for (int i = 0; i < methods.length; i++) {
        //获取方法返回值类类型
        Class returnType = methods[i].getReturnType();
        //获取返回值类型
        System.out.print(returnType.getName() + " ");

        //获取方法名
        System.out.print(methods[i].getName() + "(");

        //获取方法所有参数的类类型
        Class[] params = methods[i].getParameterTypes();
        for (Class param : params) {
            //获取参数类型
            System.out.print(param.getName() + ",");
        }

        System.out.print(")\n");
    }
}

public static void main(String[] args) {
    //如获取String对象的类信息
    APITest.printClassInfo("test");
}

打印结果:

类名:java.lang.String

方法:

boolean equals(java.lang.Object,)

java.lang.String toString()

int hashCode()

......

获取成员变量信息

/**
 * 获取成员变量
 * @param object
 */
public static void printFields(Object object){
    //先要获取类类型
    Class classType = object.getClass();

    /**
     * getFields()获取所有public成员变量信息
     * getDeclaredFields()获取所有自定义成员变量信息
     */
    //Field[] fields = classType.getFields();
    Field[] fields = classType.getDeclaredFields();
    for (Field field : fields) {
        //获取成员变量类类型
        Class fieldType = field.getClass();
        System.out.print(fieldType.getName() + " ");

        //成员变量名称
        System.out.print(field.getName() + "\n");
    }
}

public static void main(String[] args) {
    //如获取String对象的类信息
    //APITest.printClassInfo("test");
    APITest.printFields("test");
}

打印结果:

java.lang.reflect.Field value

java.lang.reflect.Field hash

java.lang.reflect.Field serialVersionUID

java.lang.reflect.Field serialPersistentFields

java.lang.reflect.Field CASE_INSENSITIVE_ORDER

获取构造方法

/**
 * 获取构造方法
 * @param object
 */
public static void printConstruct(Object object){
    //先要获取类类型
    Class classType = object.getClass();

    /**
     * getConstructors()获取所有public构造方法信息
     * getDeclaredConstructors()获取所有自定义构造方法信息
     */
    Constructor[] constructors = classType.getDeclaredConstructors();
    for (Constructor constructor : constructors) {
        //获取方法名
        System.out.print(constructor.getName() + "(");
        //获取参数类类型
        Class[] paramType = constructor.getParameterTypes();
        for (Class aClass : paramType) {
            System.out.print(aClass.getName() + ",");
        }
        System.out.print(constructor.getName() + ")\n");
    }
}

public static void main(String[] args) {
    APITest.printConstruct("test");
}

打印结果:

java.lang.String([B,int,int,java.lang.String)

java.lang.String([B,java.nio.charset.Charset,java.lang.String)

java.lang.String([B,java.lang.String,java.lang.String)

java.lang.String([B,int,int,java.nio.charset.Charset,java.lang.String)

......

 

备注:其他反射相关方法查看API

方法的反射

一个方法有方法名称和参数决定。

method.invoke(对象,参数列表);如果操作的方法没有返回值返回null,否则返回对应的值。

public class MethodReflectTest {

    public static void main(String[] args) {
        //获取testA的类类型
        TestA testA = new TestA();
        Class aType = testA.getClass();

        /**
         * 操作方法A
         */
        try {
            //获取方法
            Method methodA = aType.getMethod("methodA", int.class, int.class);
            //调用方法
            System.out.println("方法A返回结果:" + methodA.invoke(testA, 10, 5));
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("=======================================================");
        /**
         * 操作方法B
         */
        try {
            //获取方法
            Method methodB = aType.getMethod("methodB", new Class[]{int.class, int.class});
            //调用方法
            System.out.println("方法B返回结果:" + methodB.invoke(testA, new Object[]{10, 5}));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class TestA {
    public void methodA(int a, int b) {
        System.out.println(a + b);
    }

    public int methodB(int a, int b) {
        return a - b;
    }
}

打印结果:

15

方法A返回结果:null

=======================================================

方法B返回结果:5

集合的泛型

集合的泛型只是在编译阶段用来防止用户输入错误,编译之后集合是去泛型的。

绕开编译,向集合加不同类型的数据

public static void main(String[] args) {
    //定义一个泛型为String的list集合
    List<String> list = new ArrayList<>();
    //加入一个元素
    list.add("a");
    System.out.println(list);

    //获取list的类类型
    Class listType = list.getClass();
    try {
        //获取add方法
        Method methodAdd = listType.getMethod("add", Object.class);
        //通过反射向list加入一个int类型的数据
        methodAdd.invoke(list, 10);
    } catch (Exception e) {
        e.printStackTrace();
    }
    System.out.println(list);
}

打印结果:

[a]

[a, 10]


如果你喜欢我的内容,就请打赏一下吧
微信
支付宝
温馨提示: 你的打赏金额会直接转入对方账户,不可退回。

评论专区


审核通过的评论(0)
暂无评论信息
个人名片

  欢迎来到“浩瀚星尘”的个人博客!
  首先,该博客用于分享本人的生活事迹与兴趣爱好; 此外,该博客的主要作用便是与广大的小伙伴一起分享探讨开发技术, 希望大家多多关照。

网名: 浩瀚星尘
城市: 重庆
工作: java