单例模式:
这种模式叫做 “饿汉式” 单例设计模式
步骤:
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 语言访问控制并且底层构造方法是不可访问的。
如果成员是私有的,默认情况是会抛出这个异常。