关于Java反射的总结


反射的本质就是:在运行时,把 Java 类中的各种成分映射成一个个的 Java 对象。**

0.反射和类加载关系

类加载过程如下:

  1. 编译,Java 编译器将 .java 编译产生 .class 二进制文件。

  2. 加载,JVM 中的类加载器解析.class 文件内的信息。

    类加载器会根据类的全限定名来获取此类的二进制字节流,生成代表这个类的 java.lang.Class 对象。

  3. 加载结束后,JVM 开始进行连接阶段(包含验证、准备、初始化)。经过这一系列操作,类的变量会被初始化。

  4. 初始化

反射就是上述第二步,**Java 中,无论生成某个类的多少个对象,这些对象都会对应于同一个 Class 对象。**使用反射可获取class,然后进行各种操作。

  1. JVM 加载方法的时候,遇到 new User(),JVM 会根据 User 的全限定名去加载 User.class 。
  2. JVM 会去本地磁盘查找 User.class 文件并加载 JVM 内存中。
  3. JVM 通过调用类加载器自动创建这个类对应的 Class 对象,并且存储在 JVM 的方法区。注意:一个类有且只有一个 Class 对象。

1.获取Class对象的方法

3种:

  • forName

    Class c1 = Class.forName("xxx.xxx.xxx");
    
  • 通过类获取Class

    Class c2 = Boolean.class;
    
  • 通过对象 getClass

    Boolean bool = new Boolean();
    Class c3 = bool.getClass();
    

2.获取Class对象的信息

setAccessible() //是一个通用的方法,可获取到对应信息的超级权限,若当前信息有private等权限控制,该方法可拿到操作权限

构造方法

  • 获取constructors数组

    cla.getConstructors()
    
  • 获取constructor

    getConstructor(Class<?>... parameterTypes)
    
  • 获取非public的构造函数

    getDeclaredConstructor(Class<?>... parameterTypes)
    

使用对象创建实例方式见下

属性

  • 获取属性数组

    getFields()
    
  • 获取指定Field

    getField(String name)
    
  • 获取非public的属性

    getDeclaredField(String name)
    
  • 设置属性

    set(Object,param)
    

方法

  • 获取方法数组

    getMethods()
    
  • 获取指定数组

    getMethod(String name, Class<?>... parameterTypes)
    
  • 获取非public数组

    getDeclaredMethod(String name, Class<?>... parameterTypes)
    
  • 指定对象调用方法

    invoke(Object)
    

3.反射操作实例对象

判断是否为类的实例两种方式:

  1. 用 instanceof 关键字
  2. 用 Class 对象的 isInstance 方法(它是一个 Native 方法)
    ArrayList arrayList = new ArrayList();

		Boolean isList1 = arrayList instanceof List
		Boolean isList2 = List.class.isInstance(arrayList)

创建实例

  1. 用 Class 对象的 newInstance 方法,没有无参构造函数无法创建,需使用第2种。
  2. 用 Constructor 对象的 newInstance 方法。

demo:

public class TestReObject {
    private int id;
    private String name;
  
		public TestReObject(){
    }
    public TestReObject(int id,String name){
        this.id = id;
        this.name = name;
    }
}
String classString = "reflect.TestReObject";
Class cla = Class.forName(classString);
TestReObject reObject = (TestReObject) cla.newInstance();

Constructor constructor = cla.getConstructor(int.class,String.class);
TestReObject str2 = (TestReObject) constructor.newInstance(12,"abc");

PS

demo

public class AboutReflect {
    public static void main(String[] args) {
        try {
            //获取class对象
            Class cla = Class.forName("Base.ObjectTest");




            //class对象创建实例对象方式一
            ObjectTest objectTest = (ObjectTest) cla.newInstance();

            //class对象创建实例对象方式二
            Constructor constructor = cla.getConstructor(int.class, String.class);
            ObjectTest objectTest1 = (ObjectTest) constructor.newInstance(12, "abc");





            //获取 constructor数组及指定constructor
            Constructor[] constructors = cla.getConstructors();

            Constructor constructor0 = cla.getConstructor();
            Constructor constructor1 = cla.getConstructor(int.class,String.class);
            //可以获取非public的构造函数
            Constructor constructor2 = cla.getDeclaredConstructor(int.class);
            System.out.println(constructor2.getParameterCount());

            for(Constructor cons:constructors){
                System.out.println(cons.getParameterCount());
            }





            //获取属性
            Field[] fields = cla.getFields();
            System.out.println("field数量:"+fields.length);

            //获取属性的注解,拿到超级权限,然后注入到指定对象
            Field fieldId = cla.getDeclaredField("id");
            fieldId.setAccessible(true);
            fieldId.set(objectTest,fieldId.getAnnotation(TestAnnotation.class).id());

            System.out.println(objectTest.toString());




            //获取方法 并使用指定对象访问
            Method method = cla.getDeclaredMethod("print",int.class,String.class);
            method.invoke(objectTest,996,"icu");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}


class ObjectTest {
    @TestAnnotation(id=123)
    private long id;
    private String name;

    public ObjectTest() {
    }

    public ObjectTest(int id, String name) {
        this.id = id;
        this.name = name;
    }

    protected ObjectTest(int id){
        this.id = id;
    }

    public void print(int id,String name){
        System.out.println(id+"==="+name);
    }

    @Override
    public String toString() {
        return "ObjectTest{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}


@Retention(RetentionPolicy.RUNTIME)
@interface TestAnnotation {

    int id() default 1;

}

猜你喜欢

转载自blog.csdn.net/im_xiao/article/details/106014003
今日推荐