Java的反射!!!

本文详细介绍了Java反射机制的概念、用途,涵盖了获取类、构造方法、属性和方法的动态操作,包括通过Class类、Class.forName和反射API实现实例化、构造器选择、属性读写以及方法调用。还展示了如何通过反射越过泛型限制,以及在实际项目中的应用实例如AOP和数据一致性校验。
摘要由CSDN通过智能技术生成

java反射

概念:

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

用途

用途广泛,列入拦截器,aop,自定义注解等可以参考

redis实现幂等性校验
aop实现自定义注解

代码使用

(一个类只有一个class文件) clazz.newInstance() 就是获取对象

//一、通过反射获取类
        //1、获取对象的class 个人认为没啥鸟用
        Class<? extends Student> aClass = new Student().getClass();
        //2、通过类.class
        Class<Student> studentClass = Student.class;
        //3、通过Class.forName
        Class<?> aClass1 = Class.forName("com.zhk.study.Student");
        System.out.println(aClass == studentClass && aClass == aClass);//true


//二、通过反射获取构造方法并使用:   
        //1.加载Class对象
        Class clazz = Class.forName("com.zhk.study.Student");
        //2、获取所有构造方法(公有)
        Constructor[] constructors = clazz.getConstructors();
        Stream.of(constructors).forEach(System.out::print);
        //3、暴力获取所有构造方法(所有)
        Constructor[] declaredConstructors = clazz.getDeclaredConstructors();
        Stream.of(declaredConstructors).forEach(System.out::println);
        //4、获取公有的无参构造方法
        Constructor constructor1 = clazz.getConstructor(null);
        //5、获取构造对象  也可以  clazz.newInstance()   直接获取
        Student student = (Student)constructor1.newInstance();
        //6、获取私有的有参构造方法
        Constructor declaredConstructor = clazz.getDeclaredConstructor(char.class);
        //7、调用私有有参构造方法(暴力访问)
        declaredConstructor.setAccessible(true);
        Student student1 = (Student) declaredConstructor.newInstance('男');


//三、通过反射获取属性
        //1、加载Class对象
        Class aClass2 = Class.forName("com.zhk.study.Student");
        //2、获取公有字段
        Field[] fields = aClass2.getFields();
        Stream.of(fields).forEach(System.out::println);
        //3、获取所有属性
        Field[] declaredFields = aClass2.getDeclaredFields();
        Stream.of(declaredFields).forEach(System.out::println);
        //4、获取公有属性并且复制
        Field name = aClass2.getField("name");
        Object o = aClass2.getConstructor().newInstance();
        name.set(o, "藏三");
        System.out.println(((Student ) o).name);
        //5、获取私有属性值
        Field phoneNum = aClass2.getDeclaredField("phoneNum");
        Object o1 = aClass2.getConstructor().newInstance();
        phoneNum.setAccessible(true);
        phoneNum.set(o1, "123");
        System.out.println(((Student) o1).toString());
//四、通过反射方法
        //此处省略方法同上只举一个例子
        Class m = Class.forName("com.zhk.study.Student");
        //公共方法
        Method[] methods = m.getMethods();
        //获取单个方法
        m.getMethod("方法名字");
        //获取有参方法
        Method method = m.getMethod("方法名字", String.class);
        //调用方法
        Object o2 = m.getConstructor().newInstance();
        method.invoke(o2, "传参");

泛型用在编译期,编译过后泛型擦除(消失掉)。所以是可以通过反射越过泛型检查的

import java.lang.reflect.Method;
import java.util.ArrayList;
 
/*
 * 通过反射越过泛型检查
 * 
 * 例如:有一个String泛型的集合,怎样能向这个集合中添加一个Integer类型的值?
 */
public class Demo {
	public static void main(String[] args) throws Exception{
		ArrayList<String> strList = new ArrayList<>();
		strList.add("aaa");
		strList.add("bbb");
		
	//	strList.add(100);
		//获取ArrayList的Class对象,反向的调用add()方法,添加数据
		Class listClass = strList.getClass(); //得到 strList 对象的字节码 对象
		//获取add()方法
		Method m = listClass.getMethod("add", Object.class);
		//调用add()方法
		m.invoke(strList, 100);
		//遍历集合
		for(Object obj : strList){
			System.out.println(obj);
		}
	}
}

链接

反射暴力修改被final修饰变量可修改
shardingjdbc里面的类

            //获取私有属性     TableRule.class为xxx.class    actualDataNodes为xxx属性
            Field actualDataNodesField = TableRule.class.getDeclaredField("actualDataNodes");
            //去除final修饰符的影响,将字段设为可修改的
            Field modifiersField = Field.class.getDeclaredField("modifiers");
            modifiersField.setAccessible(true);
            modifiersField.setInt(actualDataNodesField, actualDataNodesField.getModifiers() & ~Modifier.FINAL);
            //可修改属性
            actualDataNodesField.setAccessible(true);
            //要修改它里面的actualDataNodes属性
            List<DataNode> newDataNodes = new ArrayList<>();
            TableRule tableRule = null;
            //赋值
            actualDataNodesField.set(tableRule, newDataNodes);

补充和泛型 clazz

//y 是实体    clz 传参Student.class
    public <T> T test(Class<T> clz,T y) {
       
		//带有泛型直接返回实体
        T t = clz.newInstance();

      
        return t;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

张航柯

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

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

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

打赏作者

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

抵扣说明:

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

余额充值