13.反射机制

一.什么是反射?

      在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制。通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以。

     想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。

获取字节码文件对象的三种方式。

       1、Class clazz1 = Class.forName("全限定类名");  //通过Class类中的静态方法forName,直接获取到一个类的字节码文件对象,此时该类还是源文件阶段,并没有变为字节码文件。

       2、Class clazz2  = Person.class;    //当类被加载成.class文件时,此时Person类变成了.class,在获取该字节码文件对象,也就是获取自己, 该类处于字节码阶段。

       3、Class clazz3 = p.getClass();    //通过类的实例获取该类的字节码文件对象,该类处于创建对象阶段 

    有了字节码文件对象才能获得类中所有的信息,我们在使用反射获取信息时,也要考虑使用上面哪种方式获取字节码对象合理,视不同情况而定。下面介绍Class类的功能。

下面举个例子

package com.java.reflection;
 
public class Person {
    String name;
    private int age;
 
    public Person() {
        System.out.println("无参构造器");
    }
 
    public Person(String name, int age) {
        System.out.println("有参构造器");
        this.name = name;
        this.age = age;
    }
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
 

    /**
     * 反射机制获取类有三种方法
     */
    @Test
    public void testGetClass() throws ClassNotFoundException {
        Class clazz = null;
 
        //1 直接通过类名.Class的方式得到
        clazz = Person.class;
        System.out.println("通过类名: " + clazz);
 
        //2 通过对象的getClass()方法获取,这个使用的少(一般是传的是Object,不知道是什么类型的时候才用)
        Object obj = new Person();
        clazz = obj.getClass();
        System.out.println("通过getClass(): " + clazz);
 
        //3 通过全类名获取,用的比较多,但可能抛出ClassNotFoundException异常
        clazz = Class.forName("com.java.reflection.Person");
        System.out.println("通过全类名获取: " + clazz);
    }
 

输入结果如下:

通过类名: class com.java.reflection.Person
无参构造器
通过getClass(): class com.java.reflection.Person
通过全类名获取: class com.java.reflection.Person

利用newInstance创建对象:调用的类必须有无参的构造器

    /**
     * Class类的newInstance()方法,创建类的一个对象。
     */
    @Test
    public void testNewInstance()
            throws ClassNotFoundException, IllegalAccessException, InstantiationException {
 
        Class clazz = Class.forName("com.java.reflection.Person");


 
        //使用Class类的newInstance()方法创建类的一个对象
        //实际调用的类的那个 无参数的构造器(这就是为什么写的类的时候,要写一个无参数的构造器,就是给反射用的)
        //一般的,一个类若声明了带参数的构造器,也要声明一个无参数的构造器
        Object obj = clazz.newInstance();
        System.out.println(obj);
    }
输出结果如下:

无参构造器
Person{name='null', age=0}

猜你喜欢

转载自blog.csdn.net/zzh8578741/article/details/81410702