介绍

  Java程序员都知道,类中private修饰的字段、方法,只能在类内部使用;那真的没有办法在类外部使用private修饰的成员么?这时本篇的主角登场了:反射机制提供在运行时,对于任意一个类,都能够访问这个类的所有信息(构造函数、字段、方法等,也不管是public还是private修饰的)。
  在java中,编写的类都是.java结尾,编译后是以.class结尾。程序运行后,.class文件加载到jvm中,转换为Class对象。类可以有多个对象,但这个类对应的Class对象仅有一个。就是通过这个Class对象,来访问类的所有信息。

获取Class对象

  有3种方式:
  1.类名.class
  2.类的实例.getClass()
  3.Class.forName(“类的全路径”);

  假设项目中,fanshe包下有一个Student类,使用上面的三种方式:

import fanshe.Student;
	
	Class aClass = Student.class;
	
	Student stu = new Student();
	Class bClass = stu.getClass();
	
	Class cClass = Class.forName("fanshe.Student");

	//都会返回true
	System.out.println(aClass == bClass);
	System.out.println(bClass == cClass);



常用方法

String aClass.getName();//获取全路径类名
String aClass.getName();//获取类名

Object aClass.newInstance();//调用无参构造函数,得到类的实例

Constructor[] aClass.getConstructors();//获取public修饰的所有构造函数
Constructor aClass.getConstructor(Class...);//获取public修饰的某个构造函数
Constructor[] aClass.getDeclaredConstructors();//获取所有的构造函数,不管哪
种修饰符
Constructor aClass.getDeclaredConstructor(Class...);//获取某个构造函数

constructor.newInstance(实参数值列表);//调用对应的构造函数,得到类的实例

Field[] aClass.getFields();//获取public修饰的所有属性(包括父类)
Field aClass.getField(String name);//获取指定名称的public修饰的某个属性(包括
父类)
Field[] aClass.getDeclaredFields();//获取所有属性,不管哪种修饰符(不包括父类)
Field aClass.getDeclaredField(String name);//获取指定名称的某个属性,不管哪种
修饰符(不包括父类)

Object field.get(实例);//获取相应属性的值
boolean field.isAccessible();//属性是否允许访问
field.setAccessible(true);//使属性允许访问
field.set(实例, 值);//属性赋值

Method[] aClass.getMethods();//获取public修饰的所有方法(包括父类)
Method aClass.getMethod(String name, Class...);//获取某个public的方法(包括
父类)
Method[] aClass.getDeclaredMethods();//获取所有方法,不管哪种修饰符(不包括
父类)
Method aClass.getDeclaredMethod(String name, Class...);//获取某个方法,不管
哪种修饰符(不包括父类)

method.invoke(Object obj, Object...);//调用对应的方法



代码示例

创建实体类
package fanShe;

import lombok.Data;

@Data
public class Father {

    /**
     * 姓名
     */
    private String name;

    /**
     * 年龄
     */
    private Integer age;

    /**
     * 身高
     */
    private Integer height;

}
package fanShe;

import lombok.Data;

@Data
public class Son extends Father {

    public Son() {
        this.score = 60;
    }

    public Son(int score, String hobby) {
        this.score = score;
        this.hobby = hobby;
    }

    /**
     * 成绩
     */
    private int score;

    /**
     * 爱好
     */
    private String hobby;

    public void sayHello() {
        System.out.println("成绩:" + score + ",爱好:" + hobby);
    }

    @Override
    public String toString() {
        return "Son{\r\n" +
                "score=" + this.score + ",\r\n" +
                "hobby='" + this.hobby + "'\r\n" +
                '}';
    }

}



获取构造函数并调用
package fanShe;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class Test {

    public static void main(String[] args) throws ClassNotFoundException, 
    IllegalAccessException, InstantiationException, NoSuchMethodException
    , InvocationTargetException {
        Class c = Class.forName("fanShe.Son");
        //调用无参的构造函数
        Object o = c.newInstance();
        System.out.println(o.toString());

		//获取第一个参数是int类型、第二个参数是String类型的构造函数
        Constructor constructor = c.getDeclaredConstructor(int.class, 
        String.class);
        //调用构造函数并给参数赋值
        Object o1 = constructor.newInstance(100, "打篮球");
        System.out.println(o1);
    }
    
}



获取属性
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Test {

    public static void main(String[] args) throws ClassNotFoundException,
    IllegalAccessException {
        Class c = Class.forName("fanShe.Son");
        //取Son类的属性
        Field[] fields = c.getDeclaredFields();
        for(int i = 0; i < fields.length; i++) {
            System.out.println(Modifier.toString(fields[i].getModifiers())
            + "," + fields[i].getName());
        }
        System.out.println("---");

        //取Son类所有的属性
        Son son = new Son(90, "学编程");
        son.setName("coder");
        son.setAge(18);
        son.setHeight(183);
        List<Field> fieldList = new ArrayList<>();
        while (c != null){
            Field[] array = c.getDeclaredFields();
            fieldList.addAll(Arrays.asList(array));
            c = c.getSuperclass();
        }

        for(Field field : fieldList) {
            boolean access = field.isAccessible();
            if(!access) {
                //不设置,取属性的值是抛异常
                field.setAccessible(true);
            }
            System.out.println(field.getName() + ":" + field.get(son));
            field.setAccessible(access);
        }
    }
    
}



获取方法并调用
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Test {

    public static void main(String[] args) throws ClassNotFoundException, 
    NoSuchMethodException, IllegalAccessException, 
    InvocationTargetException, InstantiationException {
        Class c = Class.forName("fanShe.Son");
        Constructor constructor = c.getConstructor(int.class, 
        String.class);
        Object obj = constructor.newInstance(99, "游泳");
        Method method = c.getDeclaredMethod("sayHello");
        method.invoke(obj);
    }
    
}