1、反射
反向探知,在程序运行中动态的获取或操作类中的属性
1.1 获取Class对象的四种方式
Class clazz1 = User.class;
Class<?> clazz2 = Class.forName(“com.tledu.pojo.User”);
Class<? extends User> clazz3 = new User().getClass();
Class<?> clazz4 = UserTest.class.getClassLoader().loadClass(“com.tledu.pojo.User”);
1.2 获取类的基本信息
clazz1.getPackage() 获取包名
Modifier.toString(clazz1.getModifiers()) 获取类的修饰符
clazz1.getSimpleName() 获取类名
clazz1.getClassLoader() 获取类加载器
clazz1.getInterfaces().length 获取这个类实现的接口
clazz1.getAnnotations().length 获取类的注解
clazz1.getName() 获取全类名
clazz1.getModifiers() 返回int值表示该字段的修饰符 Modifier.toString(field.getModifiers())修饰符
1.3 优缺点
优点:
增加程序的灵活性,避免固有逻辑写死到程序中
代码相对简洁,可以提高程序的复用性
缺点:
相比于直接调用反射有比较大的性能销毁(native、checkMemberAccess)
内部暴露和安全隐患
2、反射的属性操作
通过反射的newInstance()方法创建对象
User user = (User) clazz.newInstance();
getFields() 获取本类及父类中的公共的属性
Field[] fields = clazz.getFields();
for (Field field : fields) {
System.out.println(Modifier.toString(field.getModifiers())+" "+field.ge
tName());
}
getDeclaredFields() 获取本类中的所有属性包括私有的
对于私有的属性在操作时要开放权限 field.setAccessible(true);
Field field = clazz.getDeclaredField(“name”);
field.setAccessible(true);
field.set(user, “小王”);
关于静态属性的赋值
Field field2 = clazz.getDeclaredField(“address”);
field2.set(null, “湖南”);
System.out.println(field2.get(null));
3、反射的方法操作
getMethods() 获取本类及父类的公共的方法
getDeclaredMethods() 获取本类中所有的方法
method.invoke() 调用method方法
第一个参数是方法名,第二个参数是可变参数是class类型的(如String.class Interger.class)
如果是静态方法,方法调用第一个参数是 null
Method method = clazz1.getDeclaredMethod ( “eat”) ;
method.invok(user) ;
4.反射的构造器操作
getDeclaredConstructors() 获取类中的构造器
Constructor constructor = clazz.getDeclaredConstructor(String.class,String.class);
User user2 = constructor.newInstance(“田源”,“男”);
5.单例破局
单例模式类:public class Singleton{…}
Class< Singleton> clazz = Singleton.class;
Constructor< Singleton> constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
Singleton s3 = constructor.newInstance();
Singleton s4 = constructor.newInstance();
System.out.println(s3);
System.out.println(s4);