Java之反射初步了解

反射

基本概念

“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”,如Python,Ruby是动态语言;显然C++,Java,C#不是动态语言,但是JAVA有着一个非常突出的动态相关机制:Reflection。

​ JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

如何获取反射的源头

Class类 的对象可以表示一个正在运行的java类或者接口
Class对象就是反射的源头
一个类在java到内存中后就存在一个表示该类型的Class对象,Class对象是唯一的
Class对象中存着这个类的所有内容(成员,构造器…)
如果能够获取到一个类的Class对象,就能够做任何事情,所有Class类的对象作为反射的源头

如何获取反射的源头:
1.类名.class
2.对象.getClass()
3.Class.forName(“包名+类名”) 推荐

package reflect01;

import java.lang.reflect.Modifier;

public class Demo02 {
	public static void main(String[] args) throws ClassNotFoundException {
		//1.类名.class
		Class cls1=String.class;
		System.out.println(cls1);
		//2.对象.getClass();
		Class cls2="哈哈".getClass();
		System.out.println(cls1==cls2);
		//3.Class.forName("包名+类名");
		Class cls3=Class.forName("java.lang.Object");
		System.out.println(cls3);
		
		//根据反射的方式获取到这个类型的父类
		Class cls4=cls1.getSuperclass();
		System.out.println(cls4);
		System.out.println(cls3==cls4);
		
		//获取基本数据类型的class对象
		//根据包装类型,TYPE属性获取对应数据类型的Class对象
		Class cls5=int.class;
		Class cls6=Integer.class;
		Class cls7=Integer.TYPE;
		System.out.println(cls5==cls6);//int.class 不等于 Integer.class
		System.out.println(cls5==cls7);//int.class  等于 Integer.class
		
		//getName()
		System.out.println(cls1.getName());
	
		//getMOdifiers()  报错 待会造
		System.out.println(cls1.getModifiers());
		System.out.println(Modifier.toString(cls1.getModifiers()));//public final
	}
}

Java的反射机制,可以实现的功能

  1. 在运行时判断任意一个对象所属的类;
  2. 在运行时判断任意一个对象所属的类;
  3. 在运行时判断任意一个类所具有的成员变量和方法;
  4. 在运行时调用任意一个对象的方法
  5. 生成动态代理

我们主要学习如何通过反射获取构造函数、给变量赋值以及调用方法。

预热:反射常用的方法
package reflect01;

public class Modifier {
	public static void main(String[] args) throws ClassNotFoundException {
		//1.类名.class
		Class cls1=String.class;
		System.out.println(cls1);
		//2.对象.getClass();
		Class cls2="哈哈".getClass();
		System.out.println(cls1==cls2);
		//3.Class.forName("包名+类名");
		Class cls3=Class.forName("java.lang.Object");
		System.out.println(cls3);
		
		//根据反射的方式获取到这个类型的父类
		Class cls4=cls1.getSuperclass();
		System.out.println(cls4);
		System.out.println(cls3==cls4);
		
		//获取基本数据类型的class对象
		//根据包装类型,TYPE属性获取对应数据类型的Class对象
		Class cls5=int.class;
		Class cls6=Integer.class;
		Class cls7=Integer.TYPE;
		System.out.println(cls5==cls6);
		System.out.println(cls5==cls7);
		
		//getName()
		System.out.println(cls1.getName());
	
		//getMOdifiers()  报错 待会造
		System.out.println(cls1.getModifiers());
		System.out.println(Modifier());
	}
}
一、反射之获取构造函数
用法示例
	/*
	 *  通过反射获取构造器,创建对象
	 *  1.
		 Constructor<T> getConstructor(Class<?>... parameterTypes) 
		 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。
	  	2.
	  	 Constructor<?>[] getConstructors()  
	  	 返回一个包含某些 Constructor 对象的数组,这些对象反映此 Class 对象所表示的类的所有公共构造方法
	  	3. 
		 Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) 
    	 返回一个 Constructor 对象,该对象反映此 Class 对象所表示的类或接口的指定构造方法。
    	4. 
		Constructor<?>[] getDeclaredConstructors() 
		返回 Constructor 对象的一个数组,这些对象反映此 Class 对象表示的类声明的所有构造方法。
		
		
		创建对象:
			通过指定的构造器创建对象,如果私有,放开权限
			通过一个类的Class对象的newInstance方法创建这个类的实例,默认调用空构造
	 * 
	*/
	
	public static void testConstruction(Class cls) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
		//1.获取构造器,通过 类对象.getConstructors,根据类对象的方法获取构造器
		Constructor[] arr=cls.getConstructors();//所有的公共的
		System.out.println(Arrays.toString(arr));
		//根据构造器的newInstance(实参)
		PersonOne p=(PersonOne) arr[0].newInstance("张三",15,180.52);
		System.out.println(p);
		//获取指定类型的构造器
		Constructor<PersonOne> con=cls.getDeclaredConstructor(String.class);
		//放开构造器的权限
		con.setAccessible(true);
		PersonOne p2=con.newInstance("lisi");//报错
		con.setAccessible(false);
		
		//默认调用空构造
		PersonOne p3=(PersonOne) cls.newInstance();
		System.out.println(p3);
		
	}
调用
public class Demo03 {
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, NoSuchFieldException {
		//传入一个类对象,这个对象是Person.class
		System.out.println("构造器测试");
		testConstruction(PersonOne.class);
	}
}
二、反射之使用修改属性
用法示例
//可以在形参加上 泛型
	public static void testField(Class<PersonOne> cls) throws NoSuchFieldException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException{
		/*
		 * 	Field getField(String name) 
      		返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。 
			Field[] getFields()  
			Field getDeclaredField(String name) 
      		返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。
			Field[] getDeclaredFields()  
	
			获取属性的值: Object get(Object obj)  
			设置属性的值: void set(Object obj, Object value) 
		 * 
		 */
		//1.获取一个Field对象,这个对象是用来修改属性的
		Field name=cls.getDeclaredField("name");//获取 方法中 公共的访问成员接口并封装成一个Field对象
		System.out.println(name);//打印的是 包名+类名+属性名
		//2.给变量赋值
			//2.1通过获取构造器,创建对象
			Constructor<PersonOne> personOne=cls.getConstructor(String.class,int.class,Double.TYPE);
			//2.2通过构造器(构造器),创建对象
			PersonOne personTwo=personOne.newInstance("小黄",20,190.0);
			//2.3直接通过对象修改变量
			System.out.println("修改之前");
			name.setAccessible(true);
			System.out.println(name.get(personTwo));//由于name返回的这个字段是私有的,无法直接访问和修改
			personTwo.setName("大黄");
			System.out.println("修改之前");
			System.out.println(name.get(personTwo));
			name.setAccessible(false);
	}
调用
public class Demo03 {
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, NoSuchFieldException {
		System.out.println("属性测试");
		testField(PersonOne.class);
	}
}
三、反射之调用方法
用法示例
//测试方法,通过对象调用成员方法
	public static void testMethod(Class<PersonOne> cls) throws InstantiationException, IllegalAccessException, NoSuchFieldException, SecurityException, IllegalArgumentException, InvocationTargetException{
		/*
		 *  通过反射获取方法,调用方法
		 	 Method getDeclaredMethod(String name, Class<?>... parameterTypes) 
			          返回一个 Method 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明方法。 
			 Method[] getDeclaredMethods() 
			 Method getMethod(String name, Class<?>... parameterTypes) 
			          返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。 
			 Method[] getMethods() 
			 
			 执行方法:
			 	Object invoke(Object obj, Object... args) 
	 			参数1: 调用方法的对象
	 			参数2: 调用方法的实参
	 			返回值: 调用方法的返回值
		 */
		//1.获取所有方法
		Method[] arr=cls.getMethods();
		for(Method m:arr){
			System.out.println(m);
		}
		//2.创建对象,直接通过类对象.newInstance.默认空参
		PersonOne p=cls.newInstance();
		//3.返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。
		Field field=cls.getDeclaredField("name");
			field.setAccessible(true);
			System.out.println(field.get(p));
			field.setAccessible(false);
		//4.调用方法,传入的对象是 filed
		System.out.println(arr[8].invoke(p,"位置"));
		
	}
调用
public class Demo03 {
	public static void main(String[] args) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, NoSuchFieldException {
		System.out.println("方法测试");
		testMethod(PersonOne.class);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值