Java 反射

Java 反射

Java 反射概述

  1. JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
  2. 而需要解剖一个类,那么我们第一件事肯定是获取到该类的字节码文件对象。
  3. 获取到该类的字节码文件后,我们使用Class中的方法进行解剖。

Class的原理

  • Class 何德何能能够担任解剖的任务呢?那是因为所有的Java类都继承了object这个类,而object这个类中有一个方法:getclass(),它可以获取该类的已经实例化的对象。

获取Class对象

  • 首先,我们先创建一个供我们解剖的Student类,如下:
public class Student {
		//默认的构造方法
		Student(String str){
			System.out.println("默认的构造方法 s = " + str);
		}
		
		//无参构造方法
		public Student(){
			System.out.println("调用了公有、无参构造方法执行了。。。");
		}
		
		//有一个参数的构造方法
		public Student(char name){
			System.out.println("姓名:" + name);
		}
		
		//有多个参数的构造方法
		public Student(String name ,int age){
			System.out.println("姓名:"+name+"年龄:"+ age);
		}
		
		//受保护的构造方法
		protected Student(boolean n){
			System.out.println("受保护的构造方法 n = " + n);
		}
		
		//私有构造方法
		private Student(int age){
			System.out.println("私有的构造方法   年龄:"+ age);
		}
}
  • 既然前面说解剖的工具在Class中,那么我们怎么获取Class呢?有以下三种方式:
  1. Class类的forName方法,此种方式需要包名+该类名,如下:
Class<?> aClass = Class.forName("com.haicoder.reflect.Student");

包名:com.haicoder.reflect,类名:Student。

  1. 对象的getClass()方法,如下:
 Student student = new Student();
 Class<? extends Student> aClass1 = student.getClass();

此种方式已经创建对象,所以反射会显得多此一举。

  1. 使用类名加.class,如下:
 Class classes = Student.class;

但是此种方式需要导入类的包,依赖性太强。

  1. 通过ClassLoader对象的loadClass()方法,如下:
Class<?> aClass2 = ClassLoader.getSystemClassLoader().loadClass("com.haicoder.reflect.Student");

获取类所有构造函数

流程如下:
步骤方法
加载Class对象Class.forName()
获取类的所有构造方法getDeclaredConstructors()
获取构造方法的所有参数getParameterTypes()
案例如下:
  • 先创建一个供测试用的Student类,如下:
public class Student {
		//默认的构造方法
		Student(String str){
			System.out.println("默认的构造方法 名字= " + str);
		}
		
		//无参构造方法
		public Student(){
			System.out.println("公有无参构造函数");
		}
		
		//有一个参数的构造方法
		public Student(char name){
			System.out.println("姓名:" + name);
		}
		
		//有多个参数的构造方法
		public Student(String name ,int age){
			System.out.println("姓名:"+name+"年龄:"+ age);
		}
		
		//受保护的构造方法
		protected Student(boolean n){
			System.out.println("受保护的构造方法 n = " + n);
		}
		
		//私有构造方法
		private Student(int salary){
			System.out.println("私有的构造方法   工资:"+ salary );
		}

}

  • 现在我们要通过反射技术获取上方Student类的所有构造函数,如下:
public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		//1.加载Class对象
		Class clazz = Class.forName("com.haicoder.reflect.Student");
		//2.获取类的所有构造方法
		Constructor [] constructors;
		constructors = clazz.getDeclaredConstructors();
		for(int i=0;i<constructors.length;i++) {
			//3.打印构造方法
			System.out.println(constructors[i]);
			//4.getParameterTypes可以得到构造方法的所有参数
			Class[] parametertypes = constructors[i].getParameterTypes();
			//5.打印参数类型名称
			for(int j=0;j < parametertypes.length;j++){
				System.out.print(parametertypes[j].getName()+" ");
			}
			System.out.println("");
		}
	}

运行结果如下:
getDeclaredConstructors

获取指定参数构造函数

  • 那么如果我们只是想获取 public Student(String name ,int age)这一个构造函数呢?
流程如下:
步骤方法
加载Class对象Class.forName()
设置参数Class[] p = { int.class, String.class
获取类的指定构造方法getDeclaredConstructor§
获取构造方法的所有参数getParameterTypes()
案例如下:
public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		// 加载Class对象
		Class clazz = Class.forName("com.haicoder.reflect.Student");
		// 获取类的指定构造方法
		Class[] p = { int.class, String.class };
		Constructor constructor;
		constructor = clazz.getDeclaredConstructor(p);
		// getParameterTypes可以得到构造方法的所有参数
		Class[] parametertypes = constructor.getParameterTypes();
		// 打印参数类型名称
		for (int j = 0; j < parametertypes.length; j++) {
			System.out.print(parametertypes[j].getName() + " ");
		}
		System.out.println("");
	}

运行结果如下:
getDeclaredConstructor

调用构造方法

  • 上方已经获取到了构造方法,那么我们怎么调用这些构造方法呢?
  • 调用公有构造函数。
流程如下:
步骤方法
调用公有构造方法constructor.newInstance(“haicoder”,22)
案例如下:
public static void main(String[] args) throws Exception {
		// 加载Class对象
		Class clazz = Class.forName("com.haicoder.reflect.Student");
		// 获取类的指定构造方法
		Class[] p = {String.class,int.class};
		Constructor constructor;
		constructor = clazz.getDeclaredConstructor(p);
		//使用newInstance方法调用构造函数
		constructor.newInstance("haicoder",22);
	}

运行结果如下:
newInstance

  • 如果调用的构造函数是私有的呢?
  • 调用私有构造函数。
流程如下:
步骤方法
取消Java语言访问检查constructor.setAccessible(true);
调用私有构造函数constructor.newInstance(“haicoder”)
案例如下:
public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		// 加载Class对象
		Class clazz = Class.forName("com.haicoder.reflect.Student");
		// 获取类的私有构造方法
		Class[] p = {int.class};
		Constructor constructor;
		constructor = clazz.getDeclaredConstructor(p);
		//取消Java语言访问检查
		constructor.setAccessible(true);
		//使用newInstance方法调用构造函数
		constructor.newInstance(90);
	}

运行结果如下:
setAccessible

调用类中的私有方法
流程如下:
步骤方法
加载Class对象Class.forName
获取类的默认构造方法class.getDeclaredConstructor
创建实例constructor.newInstance
获取私有方法getDeclaredMethod
取消Java语言访问检查method.setAccessible
调用方法method.invoke
案例如下:
public static void main(String[] args) throws Exception {
		// TODO Auto-generated method stub
		// 加载Class对象
		Class clazz = Class.forName("com.haicoder.reflect.Student");
		// 获取类的默认构造方法
		Class[] p = { String.class };
		Constructor constructor;
		constructor = clazz.getDeclaredConstructor(p);
		// 使用newInstance方法调用构造函数,创建实例
		Student student=(Student) constructor.newInstance("haicoder");
		//获取私有方法
		Class[] m = { String.class, int.class };
		Method method = clazz.getDeclaredMethod("showScore", m);
		//取消Java语言访问检查
		method.setAccessible(true);
		//输入学生信息
	    Object info[] = {"嗨客",90};
	    //调用方法
		method.invoke(student,info);
	}

运行结果如下:
methon

总结

以上为本人在看其他大牛的反射文章后,根据自己的理解,总结调试出来的结果,本人学识尚浅,如果有错误的地方,请多多指教!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

i白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值