反射的讲解以及解决反射单例的漏洞

反射讲解

概念:

在java程序运行状态中,类对象(class对象)可以动态获取类的相关信息,以及动态调用类的属性和方法

优缺点

反射的优缺点
优点
增加程序的灵活性,避免固有逻辑写死到程序中
代码相对简洁,可以提高程序的复用性
缺点
相比于直接调用反射有比较大的性能销毁
内部暴露和安全隐患

另外反射对性能会有损耗,这是为什么呢?
每次newInstance都会做安全检查 比较耗时
在这里插入图片描述

基本操作

获取类对象的四种方式// 获取类对象的四种方式

Class clazz1 = User.class;
Class<?> clazz2 = Class.forName(“com.gupao.edu.fs.User”);
Class<? extends User> clazz3 = new User().getClass();
Class<?> clazz4 = Demo03.class.getClassLoader().loadClass(“com.gupao.edu.fs.User”);

基本信息操作

获取类的相关结构

System.out.println(clazz1.getModifiers()); // 获取类的修饰符
System.out.println(clazz1.getPackage());
System.out.println(clazz1.getName());
System.out.println(clazz1.getSuperclass());
System.out.println(clazz1.getClassLoader());
System.out.println(clazz1.getSimpleName());
System.out.println(clazz1.getInterfaces().length); // 获取类似实现的所有的接口
System.out.println(clazz1.getAnnotations().length);

字段的操作

public static void main(String[] args) throws Exception {
Class userClass = User.class;
// 获取User对象
User user = userClass.newInstance();
// 获取类型中定义的字段 共有的字段以及父类中共有的字段
Field[] fields1 = userClass.getFields();
for(Field f:fields1){
System.out.println(f.getModifiers() + " " + f.getName());
}
System.out.println("--------------------");
// 可以获取私有的字段 只能够获取当前类中
Field[] fields2 = userClass.getDeclaredFields();
for(Field f:fields2){
System.out.println(f.getModifiers() + " " + f.getName());
}

// 获取name字段对应的Field
Field nameField = userClass.getDeclaredField(“name”);
// 如果要修改私有属性信息那么我们需要放开权限
nameField.setAccessible(true);
nameField.set(user,“test”);
System.out.println(user.getName());
// 如果对静态属性赋值
Field addressField = userClass.getDeclaredField(“address”);
addressField.set(null,“汪汪汪”);
System.out.println(User.address);
}

类中的方法操作

public static void main(String[] args) throws Exception {
User user = new User();
Class userClass = User.class;
// 可以获取当前类及其父类中的所有的共有的方法
Method[] methods = userClass.getMethods();
for (Method m : methods) {
System.out.println(m.getModifiers() + " " + m.getName());
}
System.out.println("**********");
// 获取本类中的所有的方法 包括私有的
Method[] declaredMethods = userClass.getDeclaredMethods();
for (Method m:declaredMethods){
System.out.println(m.getModifiers() + " " + m.getName());
}
Method jumpMethod = userClass.getDeclaredMethod(“jump”);
// 放开私有方法的调用
jumpMethod.setAccessible(true);
jumpMethod.invoke(user);
Method sayMethod = userClass.getDeclaredMethod(“say”, String.class);
// 静态方法调用
sayMethod.invoke(null,“111”);
}

构造器的操作

public static void main(String[] args) throws Exception {
Class userClass = User.class;
// 获取所有的公有的构造器
Constructor<?>[] constructors = userClass.getConstructors();
for (Constructor c:constructors){
System.out.println(c.getModifiers() + " " + c.getName() );
}
System.out.println("************************");
// 获取所有的构造器
Constructor<?>[] declaredConstructors = userClass.getDeclaredConstructors();
for (Constructor c:declaredConstructors){
System.out.println(c.getModifiers() + " " + c.getName() );
}
// 1.直接通过newInstance创建对象
User user = userClass.newInstance();
// 2.获取对应的Construcator对象获取实例
Constructor declaredConstructor = userClass.getDeclaredConstructor(String.class, String.class);
// 私有的构造器调用需要放开权限
declaredConstructor.setAccessible(true);
System.out.println(declaredConstructor.newInstance(“gupao”,“男”));

}

解决反射单例的漏洞

产生的原因是:反射可以调用私有的构造器造成的
怎么解决呢?
我们在私有构造器加逻辑代码,逻辑就是第一次调用正常创建,后面在调用私有构造器就会扔出运行时异常

public class SingleTest {
    private static SingleTest singleTest;
    public static Boolean flag=true;
    private SingleTest() {
        //第一次调用
        if(flag==true){
        }else {
            throw new RuntimeException("111111");
        }
        flag=false;
    }
    public  static SingleTest  getInstance(){
        if(singleTest==null){
            singleTest=new SingleTest();
        }
        return singleTest;
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值