我是靠谱客的博主 霸气鸡,最近开发中收集的这篇文章主要介绍反射——Class类,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

反射发生在程序的运行期,反射就是指在程序的运行期可以拿到一个对象的所有信息;

反射的目的就是为了解决在运行期,对某个实例一无所知的情况下,如何调用其方法。

一,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实例的三种方式:

  1. 类名.class
  2. 对象.getClass()
  3. 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: false

class name: java.lang.Runnable
class simplename: Runnable
Package name: java.lang
is interface: true
is array: false
is enum: false
is primitive: false

class name: [I
class simplename: int[]
Package name: java.lang
is interface: false
is array: true
is enum: false
is primitive: false

class 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。

 

小结:

  1. JVM为每个加载的class及interface创建了对应的Class实例来保存class及interface的所有信息;
  2. 获取一个class对应的Class实例后,就可以获取该class的所有信息;
  3. 通过Class实例获取class信息的方法称为反射(Reflection);
  4. JVM总是动态加载class,可以在运行期根据条件来控制加载class。

参考:廖雪峰Java教程:https://www.liaoxuefeng.com/wiki/1252599548343744

最后

以上就是霸气鸡为你收集整理的反射——Class类的全部内容,希望文章能够帮你解决反射——Class类所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(38)

评论列表共有 0 条评论

立即
投稿
返回
顶部