Java 反射

Posted aston

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 反射相关的知识,希望对你有一定的参考价值。

一切皆为对象,是Java的核心概念;

从这个概念出发,我们不禁要问类是不是对象?如果类也是对象,类又是谁的实例对象呢?

答案是肯定的,类也是对象,类是java.lang.Class(以下简称Class)的实例对象,Class也被成为类的类类型。

假设有类Student,如下

class Student{
    private int id;
    private String name;

    //get,set方法          
}

 

获取类的类类型有三种方法,分别如下:

1.  Class c1 = Student.class;

2.  Student  stu = new Student();

      Class cl = stu.getClass();

3.  Class cl = Class.forName("类全名");

 

我们可以通过类的类类型创建这个类的实例对象,前提是这个类有一个无参的构造函数,如下

Student  stu = (Student) c1.newInstance();

 

动态加载的概念

  编译时加载类是静态加载类,new 对象
  运行时加载类时动态加载类

 

反射使用

//获取类的名称
String className = cl.getName();
//获取类名称的简写
String classSimpleName = cl.getSimpleName();

/**
 * Method类,方法的对象
 * 一个成员方法就是一个Method对象
 * getMethods() 获取的是全部public的方法,包括从父类继承来的
 *getDeclaredMethods()获取自己声明的全部方法(public private protect),不获 
 *   取父类
 */
Method[] methods = cl.getMethods();
for (Method method : methods){
        //得到方法的返回类型
        //得到方法返回值的类类型
        Class returnType = method.getReturnType(); 
        //得到方法名
        String methodName = method.getName();

        //获取参数类型
        //得到参数列表的类型的类类型
        Class[] paras = method.getParameterTypes();
        for (Class c : paras){
                System.out.print(c.getName());
        }
}

 

通过反射获取变量

/**
 * 成员变量也是对象
 * java.lang.reflect.Field
 * Field 封装了成员变量的操作
 * getFields() 获取所有的public成员变量信息
 * getDeclaredFields() 获取该类自己声明的所有成员变量信息
 */
Field[] fields = cl.getDeclaredFields();
for (Field field : fields){
//变量的修饰符
//得到成员变量的类型的类类型
Class fieldType = field.getType();
String typeName = fieldType.getName();
//得到成员变量的名称
String fieldName = field.getName();

//打印变量类型和变量名
System.out.println(typeName + " " + fieldName);
}

 

打印构造函数信息

/**
 * 构造函数也是对象
 * java.lang.reflect.Constructor 中封装了构造函数的信息
 * getConstructors() 获取所有的public的构造函数
 * getDeclaredConstructors() 获取所有的构造函数
 */
/*Constructor[] cs = cl.getConstructors();*/
Constructor[] cs = cl.getDeclaredConstructors();
for (Constructor c : cs){
        //获取构造函数名称
        c.getName();
        //获取构造函数的类型的类类型
        c.getParameterTypes();
}

 

方法反射

/**
 * 方法的反射
 * 方法的名称和方法的参数列表可以唯一确定一个方法
 * 方法的反射操作
 * Method.invoke(对象, 参数列表)
 */
public static void main(String[] args) throws Exception{
         A a = new A();

         //获取print(int, int)方法
         //1. 首先获取类的类类型
         Class cl = a.getClass();
         /**
          * 2. 获取方法,名称和参数列表确定唯一方法
          * getMethod() 获取的是public方法
          * getDeclaredMethod() 获取全部自己声明的方法
          */
         Method method = cl.getMethod("print", new Class[]{int.class, int.class});

         //3. 方法的反射操作,是指用Method对象来进行调用
         //方法没有返回值返回null,有返回值就返回返回值
         Object object = method.invoke(a, new Object[]{1,2});
         //method.invoke(a, 1, 2);
}

 

使用反射解析注解

//1.使用类加载器加载类
Class cl = Class.forName("Student");
//2.找到类上面的注解
boolean exist = cl.isAnnotationPresent(Customize.class);

if (exist){
        //3.拿到注解实例
        Customize customize = (Customize)                         
        cl.getAnnotation(Customize.class);
        System.out.println(customize.value());
}

//4.找到方法上的注解
Method[] methods = cl.getMethods();
for (Method method : methods){
        if (method.isAnnotationPresent(Customize.class)){          
                System.out.println(((Customize)method.getAnnotation(Customize.class)).value());
        }
}

//4.1另一种解析方法
for (Method method : methods){
       Annotation[] annotations = method.getAnnotations();
       for (Annotation annotation : annotations){
               if (annotation instanceof Customize){
                       System.out.println(((Customize) annotation).value());
               }
       }
}

 

注解定义

public @interface Customize {
    String value() default "I am annotation";
}

 


以上是关于Java 反射的主要内容,如果未能解决你的问题,请参考以下文章

反射机制入门

反射机制入门

反射机制入门

使用反射在外部JAR / CLASS上调用包含Hibernate事务的方法(Java EE)

为啥我的 Ray March 片段着色器反射纹理查找会减慢我的帧速率?

OpenGL片段着色器不照亮场景