0
点赞
收藏
分享

微信扫一扫

反射(Reflect)

他说Python 2022-03-12 阅读 41

反射

概述

设计一个类,创建类的对象,正向过程
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对象,进一步就能得到某个类中组成部分
举报

相关推荐

0 条评论