反射(Reflect)

反射

概述

设计一个类,创建类的对象,正向过程
Person p = new Person(); //创建对象

反射是一个逆向的过程,包名.类名	//Class.forName("com.mysql.jdbc.Driver");

反射是一种动态获取对象的一种机制,对Java语言灵活性发货很大的作用。
作用:能够在程序运行时判断任意的一个对象所属哪个类,获取该类的属性、方法、构造方法,并且能够在任意时刻进行调用

很多框架中都要使用反射,例如:Spring、Mybatis、动态代理等都用到了反射

获取反射对象Class类对象

//1、通过Object类中getClass方法
Daily daily = new Daily();
Class aClass = daily.getClass();
//2、通过class属性
Class<Daily> dailyClass = Daily.class;
Class<Integer> integerClass = Integer.class;
//3、Class.forName
Class aClass = Class.forName("com.wjx.dto.Daily");

通过反射创建对象

1.调用无参构造方法
newInstance(); //等价于使用无参构造方法创建对象

2.获取类的构造方法,然后在调用newInstance([参数]),来创建对象
//通过Class对象获取该类无参的构造方法
Constructor<Daily> c = dailyClass.getConstructor();
System.out.println("c = " + c);
Daily daily1 = c.newInstance();//调用无参构造方法
//通过Class对象获取该类有参的构造方法
Constructor<Daily> c2 = dailyClass.getConstructor(
String.class, Double.class, Date.class, Date.class);
System.out.println("c2 = " + c2);
//通过调用有参构造方法
Daily daily2 = c2.newInstance("反射",10.0,new Date(),new Date());

通过反射获取构造器方法并使用

在反射机制中,把类的成员(构造方法、成员方法、成员变量)都封装成对应的类进行表示,其中构造方法使用类Constructor表示。可通过Class类中提供方法获取构造方法
(1)返回一个构造方法
		Constructor<T>  getConstructor(Class<?>... parameterTypes)
			获取public修饰,指定参数类型所对应的构造方法
		Constructor<T>  DeclaredConstructor(Class<?>... parameterTypes)
			获取指定类型参数所对应的构造方法(包含私有的)
			
(2)返回所有的构造方法
			Constructor<?> [] getConstructors()
				获取所有public修饰的构造方法
			Constructor<?> [] getDeclaredConstructors()
				获取所有的构造方法(包含私有的)
	
总结:
	获取构造方法步骤:
		1、获取到Class对象
		2、获取指定构造方法
		3、通过构造方法累赘newInstance()创建对象
			public T newInstance(Object ... initargs)
package com.softeem.reflect;
import com.softeem.dto.Daily;
import javax.lang.model.SourceVersion;
import java.lang.reflect.Constructor;
/**
* @author zhengwen
* @create 2022-03-08 16:07
*/
public class ConstructorDemo01 {
	public static void main(String[] args) throws Exception {
		//1.先获取Class类对象
		Class<?> aClass = Class.forName("com.softeem.dto.Daily");
		//2.通过反射获取该类的构造方法
		//获取类中无参构造方法
		//public Daily()
		Constructor<?> c1 = aClass.getConstructor();
		//获取类中有参构造方法,需要注意参数类型以及参数个数
		//public Daily(Integer id, String content)
		//注意:严格按照构造方法的参数类型 ,不能写(int.class, String.class)
		Constructor<?> c2 = aClass.getConstructor(Integer.class, String.class);
		//注意:getConstructor只能获取public修饰的构造方法
		//Constructor<?> c3 = aClass.getConstructor(String.class);
		Constructor<?> c3 = aClass.getDeclaredConstructor(String.class);
		//若要调用私有构造方法,则需要使用暴力访问才能调用
		//true -----> 开启暴力访问
		c3.setAccessible(true);
		//调用newInstance方法,来通过构造方法创建对象
		Daily daily = (Daily) c3.newInstance("JDBC");
		System.out.println("daily = " + daily);
		//获取所有的构造方法
		//aClass.getConstructors();
		Constructor<?>[] cs = aClass.getDeclaredConstructors();
		for (int i = 0; i < cs.length; i++) {
			//获取构造方法名
			//System.out.println(cs[i].getName());
			//获取构造方法修饰符 1-->public 2-->private
			//System.out.println(cs[i].getModifiers());
			//获取构造方法的参数个数
			//System.out.println(cs[i].getParameterCount());
			//获取构造方法的参数类型
			Class<?>[] parameterTypes = cs[i].getParameterTypes();
			for (Class<?> type : parameterTypes) {
			System.out.println(type);
			}
		}
	}
}

通过反射获取成员变量并使用

	在反射中,把类中成员变量使用Field类表示,可以通过Class对象中提供的方法获取成员变量
	(1)返回一个成员变量
		Field getField(String name)	返回指定的public修饰的成员变量
		Field getDeclaredField(String name)	返回指定的成员变量(包含私有的)
	(2)返回所有成员变量
		Field[] getFields()	返回所有的public修饰的成员变量
		Field[] getDeclaredFields()	返回所有的成员变量(包含私有的)

总结:
	获取成员变量的步骤:
		1、获取Class对象
		2、获取构造方法
		3、通过构造方法,创建对象
		4、获取指定的成员变量(获取的是私有的,则需要setAccessible(true)方法暴力访问)
		5、通过方法set/get,给指定对象的指定成员变量进行赋值和获取值
			public Object get(Object obj)  //获取值
			public void set(Object obj,Object value)  //设置值
 		//1、获取Class对象
        Class<Daily> dailyClass = Daily.class;
        //2、通过Class对象来创建Daily类的对象
        //newInstance--->无参构造方法
        Daily daily = dailyClass.newInstance();
Field[] fields = dailyClass.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            System.out.print(Modifier.toString(fields[i].getModifiers()));
            System.out.print(" ");
            System.out.print(fields[i].getType().getSimpleName());
            System.out.print(" ");
            System.out.print(fields[i].getName());
            System.out.println();
        }
        Field idField = dailyClass.getDeclaredField("id");
        idField.setAccessible(true);
        idField.set(daily,4);
        System.out.println(idField.get(daily));

通过反射获取成员方法

在反射中,把类中的成员方法封装成了一个Method类表示,通过Class类中提供的方法来获取:
(1)获取单个指定方法
	Method getMethod(String name,Class<?>... parameterTypes)
		获取public修饰的成员方法
	Method getDeclared(String name,Class<?>... parameterTypes)
		获取任意的成员方法(包含私有的)
(2)获取所有方法
	Method[] getMethods()
		获取本类以及父类中所有的public修饰的成员方法
	Method[] getDeclaredMethods()
		获取本类中所有成员方法(包含私有的)

获取成员方法的步骤:
	1、获取Class对象
	2、获取构造方法
	3、通过构造方法创建对象
	4、获取指定的方法
	5、执行找到的方法
		public Object invoke(Object obj,Object... args)
		//invoke方法的返回值表示执行方法的返回值结果
//1、获取Class对象
Class<User> userClass = User.class;
//2、获取User类中的所有public修饰的方法
Method[] methods = userClass.getMethods();
for(Method method : methods){
	System.out.println("method = " + method);
}
System.out.println("------------------------")
//获取指定的成员方法
//String name,Class<?>... parameterTypes
//name --->  方法名     parameterTypes --->  方法参数类型
Method show = userClass.getMethod("show");
System.out.println("show = " + show);
User user = userClass.newInstance();
//invoke ---> 执行方法
//invoke(Object obj,Class... parameterTypes)
//obj ---> 对象     Class... parametersTypes ---> 执行方法需要传入参数
Object invoke = show.invoke(user)
System.out.println("invoke = " + invoke);

System.out.println("------------获取有参无返回成员方法------------");
Method show1 = userClass.getMethod("show",String.class);
Object abc = show1.invoke(user, "abc");
System.out.println("abc = " + abc);

System.out.println("--------------获取有参有返回成员方法-----------------");
Method show2 = userClass.getMethod("show", int.class);
Object invoke1 = show2.invoke(user, 1);
System.out.println("invoke1 = " + invoke1);

反射的缺点

反射的代码比我们之前正常调用的代码要多,性能也慢,所以避免使用反射
什么时候使用反射:
	如果一个功能可以不用反射来完成,那么最好不用

反射存在的意义

反射机制是很多框架的“基石”
	.xml文件或者properties文件写好了一下配置,然后在Java类中解析xml文件或者properties文件中的内容,得到一个字符串,根据字符串来获取某一个类Class对象,进一步就能得到某个类中组成部分
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值