Java基础-反射

介绍

JAVA反射机制是指程序在运行状态时,可以动态获取某个类的成员属性,变量,方法等等。还可以动态的创建类的实例,通过类的对象调用类的方法等等的动态操作。这种动态操作称为Java的反射机制。那么在了解反射机制前需要先了解一下在Java中类是如何加载的。

在Java程序执行的时候,首先jvm会从Java硬盘中读取源文件,并将源文件(.Java文件)读取到方法区中并创建对应且唯一的class文件,也就是上图所示方法区中的类对象。这个class文件中包含着我们创建类的对象时所需要的模板信息,也就是源文件中的属性、方法等等。Class本身也是一个类,它的主要功能之一就是生成类加载时的class文件,为类的初始化及实例化做准备。而我们在程序中通过关键字new创建的对象创建的是类的对象,而不是类对象,二者的区别如图中所示。

反射的基本使用

首先创建一个Student类,里边包含私有属性、构造函数、toString方法。

public class Student {
	private String name;
	public Integer age;
	
	private void private_show() {
		System.out.println("用户名:"+name+",年龄:"+age+"!");
	}
	
	public void show() {
		System.out.println("用户名:"+name+",年龄:"+age+"!");
	}

	public Student(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}
	
}

接着我们通过反射机制动态获取类对象(类对象里包含着类的所有模板信息,我们就可以对类进行其他动态操作了)

获取类的三种方式
public class Demo {
	//获取类的三种方式
	public static void main(String[] args) throws ClassNotFoundException {
		
		//获取方式一
		Student stu1 = new Student();
		Class stu1Class = stu1.getClass();
		System.out.println(stu1Class);
		
		//获取方式二
		Class stu2Class = Student.class;
		System.out.println(stu2Class);
		
		//获取方式三
		Class<?> stuClass = Class.forName("Demo.Student");//包名.类名
		System.out.println(stu3Class);
		
		//比较是否相同
		System.out.println(stu1Class == stu2Class);
		System.out.println(stu1Class == stu3Class);
		
		//结果
		//		class Demo.Student
		//		class Demo.Student
		//		class Demo.Student
		//		true
		//		true

	}
}

需要注意的是第三种获取方式的参数格式必须是包名.类名,否则JVM无法定位这个类的具体位置。

那么三种方式最常用的是第三种方式。理由如下:

  • 第一种:需要创建对象,也就没有使用反射机制的意义了,显得多此一举。
  • 第二种:需要导入包,依赖性太强。
  • 所以选择第三种。
创建类的对象
	public static void main(String[] args) throws Exception {

		Class<?> stuClass = Class.forName("Demo.Student");
		System.out.println(stuClass);
		
		//创建类的实例
		Object obj = stuClass.newInstance();
		System.out.println(obj);

	}
	
	//输出结果
	//	class Demo.Student
	//	Student [name=null, age=null]
通过类对象调用方法、属性等
public class Demo {

	public static void main(String[] args) throws Exception {
		
		Student stu = new Student("admin",11);
		
		//获取方法——>Method

		Class<?> stuClass = Class.forName("Demo.Student");//获取class
		
		Method md = stuClass.getMethod("show"); //获取公有方法
		md.invoke(stu);	//执行方法 (参数表示要执行哪个对象的此方法)
		
		Method mdDec = stuClass.getDeclaredMethod("show"); //获取私有方法
		mdDec.setAccessible(true);	//获取调用私有方法的权限
		mdDec.invoke(stu);	//执行
		
		//获取属性——>Field

		Field field = stuClass.getField("age");	//获取公有属性
		System.out.println(field.get(stu)); 	//打印
		
		Field fieldP = stuClass.getDeclaredField("name"); //获取私有属性
		fieldP.setAccessible(true); 	//获取私有属性权限
		System.out.println(fieldP.get(stu));		//打印
	}
	
	//输出结果
	//	用户名:admin,年龄:11!
	//	用户名:admin,年龄:11!
	//	11
	//	admin
}

获取Class对象的摘要信息
Class<?> stuClass = Class.forName("Demo.Student");//获取class
		
boolean isPrimitive = stuClass.isPrimitive();//判断是否是基础类型
boolean isArray = stuClass.isArray();//判断是否是集合类
boolean isAnnotation = stuClass.isAnnotation();//判断是否是注解类
boolean isInterface = stuClass.isInterface();//判断是否是接口类
boolean isEnum = stuClass.isEnum();//判断是否是枚举类
boolean isAnonymousClass = stuClass.isAnonymousClass();//判断是否是匿名内部类
boolean isAnnotationPresent = stuClass.isAnnotationPresent(Deprecated.class);//判断是否被某个注解类修饰

String className = stuClass.getName();//获取class名字 包含包名路径
Package aPackage = stuClass.getPackage();//获取class的包信息
String simpleName = stuClass.getSimpleName();//获取class类名
int modifiers = stuClass.getModifiers();//获取class访问权限

Class<?>[] declaredClasses = stuClass.getDeclaredClasses();//内部类
Class<?> declaringClass = stuClass.getDeclaringClass();//外部类
通过反射机制获取注解信息
// 获取方法——>Method
Class<?> stuClass = Class.forName("Demo.Student");// 获取class

// 首先需要获得与该方法对应的Method对象
Method method = stuClass.getDeclaredMethod("show");
Annotation[] annotations1 = method.getAnnotations();// 获取所有的方法注解信息
TypeVariable[] typeVariables1 = method.getTypeParameters();
Annotation[][] parameterAnnotationsArray = method.getParameterAnnotations();// 拿到所有参数注解信息
Class<?>[] parameterTypes = method.getParameterTypes();// 获取所有参数class类型
Type[] genericParameterTypes = method.getGenericParameterTypes();// 获取所有参数的type类型
Class<?> returnType = method.getReturnType();// 获取方法的返回类型
int modifiers = method.getModifiers();// 获取方法的访问权限

反射机制的好处及应用场景

反射机制的好处应用场景
在运行时判定任意一个对象所属的类逆向代码 ,例如反编译
在运行时构造任意一个类的对象与注解相结合的框架
在运行时判定任意一个类所具有的成员变量和方法单纯的反射机制应用框架
在运行时调用任意一个对象的方法动态生成类框架(GSon)
  • **优点:**运行期类型的判断,动态类加载,动态代理使用反射。
  • **缺点:**性能是一个问题,反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的java代码要慢很多。

文尾

文章均为学习阶段记录笔记,若有不妥请留言指正。谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值