为了账号安全,请及时绑定邮箱和手机立即绑定

单例模式(4种),反射

标签:
Java

单例模式:
这种模式叫做 “饿汉式” 单例设计模式
步骤:
1:私有的无参构造方法
2:内部定义一个 私有的 静态的 类型本身的对象,并且直接使用无参构造初始化
3:提供一个公开的,静态的,成员方法,返回第二步中创建的对象

默认自带一种好处,线程安全的

public class MyRuntime {
    private String name;
    private int age;

    private static MyRuntime rt = new MyRuntime();

    // 提供一个private的构造方法,来抑制jvm自动添加无参构造
    private MyRuntime() {

    }

    // 定义一个public的成员方法,来返回rt这个成员变量
    public static MyRuntime getInstance() {
        return rt;
    }
}

“懒汉式” 单例模式
步骤:
1:私有的无参构造方法
2:内部定义一个 私有的 静态的 类型本身的对象,设置初始值为null
3:提供一个公开的,静态的,成员方法,先给第二步创建的对象实例化,然后再返回

lazy load 延迟加载

public class MyRuntime2 {

    // 第二步:
    private static MyRuntime2 rt = null;

    // 第一步:
    private MyRuntime2() {

    }

    // 第三步:
    public static MyRuntime2 getInstance() {
        if (rt == null) {
            rt = new MyRuntime2();
        }
        return rt;
    }
}

线程安全的 “懒汉式” 单例模式
步骤:
1:私有的无参构造方法
2:内部定义一个 私有的 静态的 类型本身的对象,设置初始值为null
3:提供一个公开的,静态的,成员方法,先给第二步创建的对象实例化,然后再返回

“懒汉式” 单例模式
lazy load 延迟加载

public class MyRuntime3 {

    // 第二步:
    private static MyRuntime3 rt = null;

    // 第一步:
    private MyRuntime3() {

    }

    // 第三步: 对象锁 MyRuntime3.class
    public static synchronized MyRuntime3 getInstance() {
        if (rt == null) {
            rt = new MyRuntime3();
        }
        return rt;
    }
}

双重验证 “懒汉式” 单例模式
步骤:
1:私有的无参构造方法
2:内部定义一个 私有的 静态的 类型本身的对象,设置初始值为null
3:提供一个公开的,静态的,成员方法,先给第二步创建的对象实例化,然后再返回

“懒汉式” 单例模式
lazy load 延迟加载

public class MyRuntime4 {

    // 第二步:
    private static volatile MyRuntime4 rt = null;

    // volatile:修饰成员变量,是告诉jvm,别优化该成员变量对应的执行指令
    // 第一步:
    private MyRuntime4() {

    }

    // 第三步: 对象锁 MyRuntime4.class
    public static MyRuntime4 getInstance() {
        if (rt == null) {
            synchronized (MyRuntime4.class) {
                if (rt == null) {
                    rt = new MyRuntime4();
                }
            }
        }
        return rt;
    }
}

Class类型
图片描述
反射:
是技术,一种方式,为了创建对象用的
访问对象成员(成员变量,成员方法)

传统方式创建对象
Student stu = new Student();
stu.getAge();
System.out.println(stu.toString());

新的方式,反射的方式创建对象

Class 类型:是所有的.class字节码文件的 抽象
类的定义:一组相关的属性和形为的集合
所有的.class 中都有 成员变量,都有构造方法,成员方法
java 创建了一个 新的类型 Class 来表示所有的.class 字节码
基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void
也表示为 Class 对象
Class 没有公共构造方法 .Class 的构造 是由jvm完成的

Class 类型的常用方法
static Class<?> forName(String className)
参数指定类的字符串表示形式(类的全名 = 包名 + 类)
// java.lang.ClassNotFoundException: Student

Class clazz = Class.forName("com.newedu.jb.day22.dp.Student");

拿到对象clazz 相当于拿到了 Student.class 的字节码文件
如何根据Class的对象Clazz,来创建Student类型的对象?

一个类中总是有 成员变量,构造方法,成员方法

将字节码 抽象为一个Class类型
将类的成员变量 抽象为一个Field类型
将类的构造方法 抽象为一个Constructor类型
将类的成员方法 抽象为一个Method类型

获取指定的构造方法

Constructor<T> getConstructor(Class<?>... parameterTypes)
返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法

Class<?>... parameterTypes:是一个可变参数,也可以理解数组是一个Class数组
除了Class.forName(),我们还可以通过什么来获取Class对象呢?
第二种:类型名.class Student.class
第三种:对象名.getclass() stu.getClass()

Constructor c1 = clazz.getConstructor(String.class, int.class, String.class);

T newInstance(Object... initargs)
使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例

通过反射访问类中的私有成员
Class clazz = Class.forName("com.newedu.jb.day19.dp.Student");
// 通过getConstructor()方法只能获取public 的构造方法
// Constructor con = clazz.getConstructor(String.class,int.class);

// 如果想获取私有的构造方法 getDeclaredConstructor(Class<?>... parameterTypes)
Constructor con = clazz.getDeclaredConstructor(String.class, int.class);
// setAccessible(true); 设置成员的强制访问

IllegalAccessException - 如果此 Constructor 对象实施 Java 语言访问控制并且底层构造方法是不可访问的。

如果成员是私有的,默认情况是会抛出这个异常。

点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
软件工程师
手记
粉丝
51
获赞与收藏
617

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消