Java注解和反射02:反射概述


动态语言 vs. 静态语言

动态语言:运行时可以改变其结构的语言,例如引进新的函数、对象甚至代码,删除原有的代码(JavaScript、PHP、Python)

静态语言:运行时不可变的语言(Java、C、C++)

但是,Java可以利用反射机制获得类似动态语言的特性

反射机制

概述

反射是Java被视为动态语言的关键,其允许程序在执行期间借助于反射API(Class)取得任何类的内部信息,并能直接操作任意对象的内部属性和方法

加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(只有这一个),这个对象封装了完整的类结构信息,就像一面镜子,透过这个镜子可以看到类的结构,因此称其为反射

正常方式:引入需要的包类名称——>通过new实例化——>取得实例对象

反射方式:实例化Class对象——>getClass()方法——>得到包类名称

功能

在运行时判断任意一个对象所属的类、构造任意一个类的对象、判断任意一个类所具有的成员变量和方法、获取泛型信息、调用任意一个对象的属性、处理注解、生成动态代理...

主要API

java.lang.Class,代表一个类

java.lang.reflect.Method,代表类的方法

java.lang.reflect.Field,代表类的成员变量

java.lang.reflect.Constructor,代表类的构造器

缺点

对性能有影响

获取Class对象

Class类是反射的根源,针对任何想动态加载、运行的类,必须先获取其Class对象

类、接口、一维数组、二维数组、注解、枚举、基本数据类型、void、Class都有Class对象

获取Class对象的五种方法:

  • 已知类名,根据类的属性class获得,Test.class(最安全可靠,性能最高
  • 已知类的某个实例,调用实例的getCalss方法获得,test1.getClass()
  • 已知全类名,调用Class类的静态方法获得,Class.forName("全类名")
  • 基本数据类型可直接根据其Type属性获得,Integer.Type
  • ClassLoader
public class Main {

    public static void main(String[] args) throws ClassNotFoundException {

        /**
         * 通过反射获取类的Class对象(唯一的一个)
         */
        Person chinese = new Chinese();

        Class<?> c1 = Chinese.class;
        Class<?> c2 = chinese.getClass();
        Class<?> c3 = Class.forName("Chinese");
        System.out.println(Integer.TYPE);

        /**
         * 一个类只有一个Class对象
         */
        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());

        /**
         * 即使不同数组对象的长度不一样,int类也只有一个Class对象
         */
        int[] arr1 = new int[10];
        int[] arr2 = new int[100];
        
        System.out.println(arr1.getClass().hashCode());
        System.out.println(arr2.getClass().hashCode());
        
        /**
         * 根据Class对象获取父类的信息
         */
        System.out.println(c1.getSuperclass());
    }
}

class Person{

    String name;

    public Person(){}

    public Person(String name){

        this.name = name;
    }
}

class Chinese extends Person{

    public Chinese(){

        this.name = "中国人";
    }
}
class Russia extends Person{

    public Russia(){

        this.name = "俄罗斯人";
    }
}