概述
反射发生在程序的运行期,反射就是指在程序的运行期可以拿到一个对象的所有信息;
反射的目的就是为了解决在运行期,对某个实例一无所知的情况下,如何调用其方法。
一,Class类
无论是class或者interface,都属于Class类的一个实例,Class类是这样定义的:
public final class Class{
private Class(){}
}
以String类为例,当JVM加载String类时,它首先读取String.class文件到内存,然后为String类创建一个Class实例并关联起来:
Class cls = new Class(String);
这个Class实例是JVM内部创建的,只有JVM能创建Class实例,JVM持有的每个Class实例都指向一个数据类型,class或者interface,每个Class实例都包含了该class的所有完整信息,包括类名,包名,父类,实现的接口,所有方法,字段等,因此,如果获取了某个Class实例,就可以通过这个实例获取到该实例对应的class的所有信息。
获取Class实例的三种方式:
- 类名.class
- 对象.getClass()
- Class.forName(完整类名)
注:Class实例在JVM中是唯一的,可以用 == 比较两个Class实例
注意 == 和 instanceof的差别:
public class Test2 {
public static void main(String[] args) {
Integer n = Integer.valueOf(123);
boolean b1 = n instanceof Integer;//true
boolean b2 = n instanceof Number;//true
boolean b3 = n.getClass() == Integer.class;//true
boolean b4 = n.getClass() == Number.class;//Compile error:操作数类型 Class<capture#2-of ? extends Integer> 和 Class<Number> 不兼容
}
}
用instanceof可以匹配指定类型以及指定类型的子类,但==可以精确的判断数据类型;
通过反射获取Class实例的信息:
public class Test2 {
public static void printClassInfo(Class cls) {
System.out.println("class name: "+cls.getName());
System.out.println("class simplename: "+cls.getSimpleName());
System.out.println("Package name: "+cls.getPackageName());
System.out.println("is interface: "+cls.isInterface());
System.out.println("is array: "+cls.isArray());
System.out.println("is enum: "+cls.isEnum());
System.out.println("is primitive: "+cls.isPrimitive()+"n");
}
public static void main(String[] args) {
printClassInfo(String.class);
printClassInfo(Runnable.class);
printClassInfo(int[].class);
printClassInfo(java.time.Month.class);
}
}
运行结果:
class name: java.lang.String
class simplename: String
Package name: java.lang
is interface: false
is array: false
is enum: false
is primitive: falseclass name: java.lang.Runnable
class simplename: Runnable
Package name: java.lang
is interface: true
is array: false
is enum: false
is primitive: falseclass name: [I
class simplename: int[]
Package name: java.lang
is interface: false
is array: true
is enum: false
is primitive: falseclass name: java.time.Month
class simplename: Month
Package name: java.time
is interface: false
is array: false
is enum: true
is primitive: false
注意:数组也是一种Class,JVM还为每一种基本类型都创建了Class,例如int.class。
如果获取了Class的一个实例,就可以通过该Class实例创建对应类型的对象:
public class Test2 {
public static void main(String[] args) {
Class cls = String.class;
try {
String str = (String)cls.getDeclaredConstructor(String.class).newInstance("Wang");
System.out.println(str);
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
| NoSuchMethodException | SecurityException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}
运行结果:
Wang
动态加载
JVM在执行Java程序的时候,不是一次全部加载所有的class,而是第一次用到class时才加载,例如:Commons Logging总是优先使用Log4j,只有当Log4j不存在时,才使用JDK的Logging。
小结:
- JVM为每个加载的class及interface创建了对应的Class实例来保存class及interface的所有信息;
- 获取一个class对应的Class实例后,就可以获取该class的所有信息;
- 通过Class实例获取class信息的方法称为反射(Reflection);
- JVM总是动态加载class,可以在运行期根据条件来控制加载class。
参考:廖雪峰Java教程:https://www.liaoxuefeng.com/wiki/1252599548343744
最后
以上就是霸气鸡为你收集整理的反射——Class类的全部内容,希望文章能够帮你解决反射——Class类所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复