反射与单例模式的实现方式

获取类的Class对象的方法

//使用new获取对象来获取类对象
Demo2 demo2 = new Demo2("小王");
Class<? extends Demo2> aClass = demo2.getClass();
System.out.println(aClass.toString());
//使用类名.class 属性
Class<?>class1 =Demo2.class;
System.out.println(class1.toString());
//通过Class.forname()方法获得该类的Class对象
Class<?> aClass1 = Class.forName("theday59.Demo2");
System.out.println(aClass1.toString());

输出结果

class theday59.Demo2
class theday59.Demo2
class theday59.Demo2

对于Class文件的常用方法

  • 获取类的全名称

    • Class<?> aClass = Class.forName("theday59.Demo2");
      String name = aClass.getName();
      System.out.println(name);
      
    • theday59.Demo2

  • 获取类的父类名称

    • Class<?> aClass = Class.forName("theday59.Demo2");
      System.out.println(aClass.getSuperclass().getName());
      
    • java.lang.Object

  • 获取接口信息

    • Class<?> aClass = Class.forName("theday59.Demo2");
      Class<?>[] interfaces = aClass.getInterfaces();
      System.out.println(Arrays.toString(interfaces));
      
    • 输出的是一个数组信息

  • 获取类的所有构造方法 获取String类的所有构造方法

    • Class<?> aClass1 = Class.forName("java.lang.String");
      Constructor<?>[] constructors = aClass1.getConstructors();
      for (Constructor c:constructors){
          System.out.println(c.toString());
      }
      
  • 获取无参构造

    • //第一种方法
      Class<?> aClass1 = Class.forName("theday59.Demo2");
      Constructor<?> constructor = aClass1.getConstructor();
      Object o = constructor.newInstance();
      System.out.println(o.toString());
      //第二种方法:使用类对象.newInstance()
      Object o1 = aClass1.newInstance();
      String s = o1.toString();
      System.out.println(o1);
      
  • 获取带参构造方法

    •  Constructor<?> constructor = aClass.getConstructor(String.class,int.class);
        Object o = constructor.newInstance("小王",20);
        System.out.println(o.toString());
        
      
    • Demo2{name=‘小王’, age=20}

  • 获取类中的方法,并调用方法

    • 获取所有的public修饰的方法 包括从父类继承的方法

      • Method[] methods = aClass.getMethods();
        
    • 获取所有的方法 包括public之外修饰方法名 (只能获得当前类的方法无法获得父类继承来的方法)

      • Method[] methods = aClass.getDeclaredMethods();
        
  • 获取单个方法

    • //获取Demo2的Class对象
      Class<?> aClass = Class.forName("theday59.Demo2");
      //获取名为eat参数类型为String的方法
      Method eat = aClass.getMethod("eat",String.class);
      //加载一个Demo2的类的对象demo2 
      Demo2 demo2= (Demo2)aClass.newInstance();
      //传入demo2和参数信息 如果有返回值还需要再加入一个Object类型的变量 如果调用的是静态方法demo2改为null
      eat.invoke(demo2,"小李");
      
    • 相当于new一个方法然后调用这个方法

  • 获取私有方法,并调用方法

    •  Demo2 demo2= (Demo2)aClass.newInstance();
      Method flash = aClass.getDeclaredMethod("flash", String.class);
      //暴力反射
      flash.setAccessible(true);
      flash.invoke(demo2,"xian");
      
  • 可以调用任何方法的通用方法

    •  public static Object invokeAny(Object obj, String methodName, Class<?>[] types, Object... args) throws Exception {
        		//获取类对象
              Class<?> class1 =obj.getClass();
              //通过方法名和参数获取方法
              Method method = class1.getDeclaredMethod(methodName,types);
              //当方法为private修饰时需要进行暴力反射
              method.setAccessible(true);
           	//返回反射的Object类对象
              return method.invoke(obj,args);
          }
      
  • 应用

    • //有一个Demo2类 其内有一个 private修饰的wash方法 参数为String类型
      public class Demo2 {
      private void wash(String name){
          System.out.println("private"+name+"吃完饭刷筷子");
      }
      }
      
    //新建一个Demo2对象
    Demo2 demo2 = new Demo2();
    //依次导入Demo2对象、方法名称、方法参数类型注意是一个数组类型需要new一个Class的数组,然后根据Class数组内的参数类型依次填入所要添加的的数据
    invokeAny(demo2,"wash",new Class[]{String.class},"小王");
    
    • 输出:private小王吃完饭刷筷子
  • 获取类中的属性

    • //获取字段信息 返回的是一个字段数组 该方法只能获得public修饰的字段
      Field[] fields = aClass.getFields();
      //获取当前Class对象的所有字段信息  包括私有、默认、保护
      Field[] fields = aClass.getDeclaredFields();
      //获取单个属性 获取名为name的字段信息
       Field name = aClass.getDeclaredField("name");
      //设置字段信息和获取字段信息
      Field name = aClass.getDeclaredField("name");
       Demo2 demo2 = (Demo2) aClass.newInstance();
       name.setAccessible(true);
       name.set(demo2,"xian");
       name.get(demo2);
      

设计模式

工厂设计模式

  • 工厂模式主要负责对象创建的问题
  • 开闭原则,对拓展开放,对修改关闭 可以对工厂模式拓展新的对象,不允许修改工厂中的代码
  • 可以通过反射进行工厂模式的设计,完成动态的对象创建

恶汉式单例

  • public class Person {
        //1.首先创建一个常量
        private static final Person person = new Person();
        //2.私有化构造方法,类外部无法创建对象
        private Person(){}
        //3.通过一个公有的静态方法返回这个对象
        public static  Person getInstance(){
            return person;
        }
    }
    
  • 优点

    • 线程安全
  • 缺点

    • 生命周期太长,浪费空间

懒汉式

  • public class Student {
        //1.首先创建一个对象,设为null
        private static Student student=null;
        //2.私有化构造方法
        private Student(){}
        //3.通过公开方法返回对象
        public  static Student getInstance(){
         
                if (student==null){
                student=new Student();}
            return student;
        }
    }
    
  • 优点:只有在调用getInstance方法时才会实例化 生命周期短 节省空间

  • 缺点:线程不安全 需要同步

  • 基于线程安全的加锁方法

    • public class Student {
          private static volatile Student student = null;
      
          private Student() {
          }
      
          public static Student getInstance() {
              //
              if (student == null) {
                  synchronized (Student.class) {
                      if (student == null) {
                          student = new Student();
                      }
                  }
              }
              return student;
          }
      }
      

懒汉式静态内部类写法

  • 该方法既有生命周期短,节省空间的优点也有饿汉式的线程安全的优点

  • public class Teacher {
        //构建私有的构造方法
        private Teacher() {
        }
    	//构造静态的内部类方法
        private static class Holder {
            private static Teacher teacher = new Teacher();
        }
    	//返回并调用静态的内部类	
        public static Teacher getInstance() {
            return Holder.teacher;
        }
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值