java核心--反射

反射

反射即反向探知,比如考古学家根据发掘的物品来探知以前的事情。
指在Java程序运行状态中,
1,对于给定的一个类(Class)对象,可以获得这个类(Class)对象的所有属性和方法;
2,对于给定的一个对象,能够调用它的任意一个属性和方法。
这种动态获取类的内容以及动态调用对象的方法和获取属性的机制。就叫做JAVA的反射机制。

Class clazz = Person.class
//获取一个实例对象
Person person = clazz.newInstance();
// 获取类型中的方法
Method method = clazz.getDeclaredMethod("run");
// 通过反射执行方法
method.invoke(person);

反射的优缺点

优势

增加程序的灵活性,避免将固有的逻辑程序写死到代码里
代码简洁,可读性强,可提高代码的复用性

缺点

相较直接调用在量大的情景下反射性能下降
内部暴露和安全隐患

反射到底慢在哪些地方

需要调用native方法
每次newInstance(),都会做安全检查
寻找类Class字节码的过程

反射的基本操作

获取类对象,四种

Class<User> clazz1 = User.class;
Class<?> clazz2 = Class.forName("com.fs.User");
Class<? extends User> clazz3 = new User().getClass();
Class<?> clazz4 = Demo.class.getClassLoader().loadClass("com.fs.User");

获取类的基本信息

// 获取类的相关结构
clazz1.getModifiers(); //获取类的修饰符1025=1+1024=public abstact
clazz1.getPackage();//包名
clazz1.getName();//类全名
clazz1.getSuperclass();//父类
clazz1.getClassLoader();//类加载器
clazz1.getSimpleName();//简单名称
clazz1.getInterfaces(); // 获取类实现的所有的接口
clazz1.getAnnotations();//获取类的所有注解

修饰符 八位二进制数字表示
在这里插入图片描述

获取类的字段

// 获取类中定义共有的字段,以及父类中共有的字段
Field[] fields1 = clazz.getFields();
// 可以获取私有的字段  只能够获取当前类中
Field[] fields2 = clazz.getDeclaredFields();
// 获取指定名称Field
Field nameField = clazz.getDeclaredField("name");
// 如果要修改私有属性信息那么我们需要放开权限
nameField.setAccessible(true);
nameField.set(user,"AJ");
// 对静态属性赋值
nameField.set(null,"HN");

类的方法操作

// 获取类以及父类中的共有的方法
Method[] methods = clazz.getMethods();
// 获取类中的方法,包括私有的
Method[] declaredMethods = clazz.getDeclaredMethods();
// 获取类中指定名称的方法
Method run1 = clazz.getDeclaredMethod("run");
// 放开私用方法执行
run.setAccessible(true);
run1.invoke(user);
// 获取类中指定名称和参数的方法
Method run = clazz.getMethod("run", String.class);
// 静态方法调用
run.invoke(null,"777");

类的构造器操作

 //获取类中所有的公有构造器
Constructor[] cons = clazz.getConstructors();  
//获取类中所有的构造器         
Constructor[] cons1 = clazz.getDeclaredConstructors(); 
//class直接调用默认无参构造
Person.class.newInstance(); 
//获取类中无参的构造器      
Constructor conNoParam= clazz.getDeclaredConstructor();   
conNoParam.newInstance(); //构造器实例对象
//获取类中有参构造    
Constructor con = clazz.getDeclaredConstructor(String.class);   
con.setAccessible(true); //私用的构造器放开权限
con.newInstance("abc");//有参构造调用

破局反射破坏单例

原因:反射可以调用类中私用的构造器
解决方案:在私用构造器中加入逻辑判断

if(Single.instance !=null){
	throw new RunTimeException("实例已经创建了");
}

反射的使用场景

SpringIOC
Mybatis
JDBC


版权声明:本文为z958479原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。