Author:赵志乾
Date:2019-05-03
Declaration:All Right Reserved!!!
1、Class实例由来
Java语言中,除了基本类型外,其他类型都统称引用类型。而每一种引用类型都是JVM所引入广义类型的特例,其依据能持有的实例不同而有所区分。为了明确表征一个引用类型,JVM进程在内存中使用Class的一个实例来存储引用类型的所有信息,如:该引用类型有哪些构造函数、字段、方法、实现了哪些接口、继承了哪个类等等。其实说白了,Class的一个实例就是一个字节码文件在内存中的表征。
故此,JVM进程每加载一个引用类型,JVM就会为其在内存中创建一个Class实例。当我们需要获取关于某个引用类型的任何信息时,都可以通过其在内存中对应的Class实例来获取。而通过Class实例获取引用类型相关信息的方式称之为反射。
2、Class实例获取
方法1:通过引用类型来获取,假设引用类型为Type,则获取其在内存中对应Class实例的方法为Type.class。
Class<?> cls = String.class;
方法2:通过引用类型实例来获取(前提是该引用类型可以实例化,且已获得对应实例),假设实例为s,则获得所引用的实例在内存中对应的Class实例的方法为s.getClass()。
String s="my string";
Class<?> cls = s.getClass();
方法3:通过引用类型权限定名来获取,假设引用类型全限定名为fullname,则获取其在内存中对应Class实例的方法为Class.forName()。
Class<?> cls = Class.forName("java.lang.String");
注意1:方法3会抛出受检异常ClassNotFoundException。
注意2:Class实例在一个JVM进程中是唯一的,所以上述3种方法获取的都是同一个实例,可以使用==进行判断。而通过instanceof关键字也可以检验引用类型和实例的关系,但和==判断是有区别的。instanceof在所检实例为引用类型的实例或者子类型的实例时均会返回true,而==是进行严格相等判断。
3、反射用途
通过引用类型在内存中的Class实例,来获取引用类型相关信息的方式称作反射。由反射定义,可以看出,反射的目的就是要获取引用类型相关信息,以备后续使用。
用途1:信息获取与实例化
Class<?> cls = Class.forName("java.lang.String");
//基本信息获取
cls.getName();
cls.getSimpleName();
cls.getPackage();
cls.isInterface();
cls.isEnum();
cls.isArray();
cls.isPrimitive();
//创建实例
cls.newInstance();
用途2:动态加载
利用JVM动态加载引用类型的特性,在运行期依据条件的不同而加载不同的实现类。