一.简介:

Java程序中引用变量的类型,分为编译类型和运行类型,编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。

编译时根本无法预知该对象和类可能属于那些类,程序只依靠运行时信息来发现该对象和类的真实信息,这就用到反射。

 

二.示例

public interface TestInterface {
}
public class Person implements Serializable,TestInterface{
    private Long id;
    private String name;

    public Person() {
        this.id = 100L;
        this.name = "name";
    }

    public Person(Long id, String name) {
        this.id = id;
        this.name = name;
    }

    public Person(Long id) {
        super();
        this.id = id;
    }

    private Person(String name) {
        super();
        this.name = name+"private_Person";
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String toString() {
        return "Person [id=" + id + ", name=" + name + "]";
    }
    private String getSomeThing() {
        return "getSomeThing";
    }

    private void testPrivate(){
        System.out.println("private testPrivate");
    }

}


 

public class ReflectTest {
    public String className=null;
    public Class<?> personClass=null;

    /**
     * 反射Person类
     * @throws Exception
     */
    @Before
    public void init() throws Exception{
        className="com.lm.test.java.reflect.Person";
        personClass=Class.forName(className);
    }

    /**
     * 获取某个class文件对象
     * @throws Exception
     */
    @Test
    public void getClassName() throws Exception{
        System.out.println(personClass);
    }

    /**
     *获取某个class文件对象的另一种方式
     */
    @Test
    public void getClassName2() throws Exception {
        System.out.println(Person.class);
    }

    /**
     * 创建一个class文件表示实例对象,底层会调用空参的构造方法
     * @throws Exception
     */
    @Test
    public void getNewInstance() throws Exception{
        System.out.println(personClass.newInstance());
    }

    /**
     * 获取非私有的构造函数
     * @throws Exception
     */
    @Test
    public void getPublicConstructor() throws Exception{
        Constructor constructor = personClass.getConstructor(Long.class, String.class);
        Person person = (Person) constructor.newInstance(100L, "lisi");
        System.out.println(person.getId());
        System.out.println(person.getName());
    }

    /**
     * 获取私有的构造函数
     * @throws Exception
     */
    @Test
    public void getPrivateConstructor() throws Exception{
        Constructor declaredConstructor = personClass.getDeclaredConstructor(String.class);
        declaredConstructor.setAccessible(true); //强制取消Java权限检查
        Person person = (Person) declaredConstructor.newInstance("lisi2");
        System.out.println(person.getName()+" getPrivateConstructor");
    }

    /**
     * 获取非私有成员函数
     * @throws Exception
     */
    @Test
    public void getNotPrivateField() throws Exception{
        Constructor<?> constructor = personClass.getConstructor(Long.class, String.class);

        Object object = personClass.newInstance();
        Method toStringMethod = personClass.getMethod("toString");
        Object object2 = toStringMethod.invoke(object);
        System.out.println(object2);
    }

    /**
     *获取私有的成员函数
     */
    @SuppressWarnings("unchecked")
    @Test
    public void getPrivateMethod() throws Exception {
        Object obj = personClass.newInstance();//获取空参的构造函数
        Method method = personClass.getDeclaredMethod("getSomeThing");
        method.setAccessible(true);
        Object value = method.invoke(obj);
        System.out.println(value);

    }
    /**
     *
     */
    @Test
    public void otherMethod() throws Exception {
        //当前加载这个class文件的那个类加载器对象
        System.out.println(personClass.getClassLoader());
        //获取某个类实现的所有接口
        Class[] interfaces = personClass.getInterfaces();
        for (Class class1 : interfaces) {
            System.out.println(class1);
        }
        //反射当前这个类的直接父类
        System.out.println(personClass.getGenericSuperclass());

        //判断当前的Class对象表示是否是数组
        System.out.println(personClass.isArray());
        System.out.println(new String[3].getClass().isArray());

    }
}