目录
java单例模式--懒汉式、饿汉式
1、要点
2、单例模式的类型(五种)
2.1 饿汉式
2.2 枚举饿汉式(推荐使用)
2.3 懒汉式单例
2.4 DCL懒汉式(双检锁的懒汉式)
2.5 内部类懒汉式(推荐使用)
3、jdk中的体现
1、饿汉式的单例模式
2、枚举饿汉式
3、懒汉式的DCL(双检锁)
4、内部类懒汉式
单例模式,属于创建类型的一种常用的软件设计模式。(23种设计模式之一)通过单例模式的方法创建的类在当前进程中只有一个实例
构造器私有化
定义静态变量存储这个对象唯一实例
直接暴露或者封装使用getter方法提供实例的获取
饿汉式、枚举饿汉式、懒汉式、双锁懒汉式、内部类懒汉式 五种
饿汉式:即当类初始化的时候就创建实例对象 --就叫做饿汉式
代码
package com.sofwin.singletonDemo;
/**
* @packageName: com.sofwin.singletonDemo
* @author: wentao
* @date: 2022/11/21 10:00
* @version: 1.0
* @email [email protected]
* @description: 单例模式-饿汉式
*
* 要点:
* 1.构造器私有化
* 2.定义静态常量存储对象唯一实例
* 3.通过getter方法获取实例对象
*/
public class Singleton01 {
/**
* 构造器私有化
*/
private static final Singleton01 SINGLETON_01 = new Singleton01();
private Singleton01() {
System.out.println("private Singleton01");
}
public static Singleton01 getSingleton01() {
return SINGLETON_01;
}
/**
* 通过调用静态方法,实现类的初始化
* 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
*/
public static void otherMethod() {
System.out.println("判断是懒汉式还是饿汉式");
}
}
测试
package com.sofwin.singletonDemo;
import org.junit.Test;
/**
* @packageName: com.sofwin.singletonDemo
* @author: wentao
* @date: 2022/11/21 10:09
* @version: 1.0
* @email [email protected]
* @description: 单例模式的测试
*/
public class SingletonTest {
//单例模式-饿汉式
@Test
public void SinletonTest01() {
//先判断是否类初始化的时候就创建对象了
Singleton01.otherMethod();
System.out.println("=================");
Singleton01 singleton01 = Singleton01.getSingleton01();
Singleton01 singleton02 = Singleton01.getSingleton01();
System.out.println(singleton01);
System.out.println(singleton02);
}
}
(类加载就创建实例---饿汉式)
这种设计有三种方法可以进行破坏
1、反射破坏单例
package com.sofwin.singletonDemo;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @packageName: com.sofwin.singletonDemo
* @author: wentao
* @date: 2022/11/21 10:09
* @version: 1.0
* @email [email protected]
* @description: 单例模式的测试
*/
public class SingletonTest {
//单例模式-饿汉式
@Test
public void SinletonTest01() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
//先判断是否类初始化的时候就创建对象了
Singleton01.otherMethod();
System.out.println("=================");
Singleton01 singleton01 = Singleton01.getSingleton01();
Singleton01 singleton02 = Singleton01.getSingleton01();
System.out.println(singleton01);
System.out.println(singleton02);
System.out.println("暴力破解");
SingletonTest.reflection(Singleton01.class);
}
/**
* 反射破坏单例pos
* @param clazz 类对象
*/
public static void reflection(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取无参构造方法
Constructor declaredConstructor = clazz.getDeclaredConstructor();
//暴力破解
declaredConstructor.setAccessible(true);
//通过反射创建实例对象
Object o = declaredConstructor.newInstance();
System.out.println(o);
}
}
通过反射暴力破解,得到新的实例对象
改进
package com.sofwin.singletonDemo;
/**
* @packageName: com.sofwin.singletonDemo
* @author: wentao
* @date: 2022/11/21 10:00
* @version: 1.0
* @email [email protected]
* @description: 单例模式-饿汉式
*
* 要点:
* 1.构造器私有化
* 2.定义静态常量存储对象唯一实例
* 3.通过getter方法获取实例对象
*/
public class Singleton01 {
/**
* 构造器私有化
*/
private static final Singleton01 SINGLETON_01 = new Singleton01();
private Singleton01() {
//防止反射破坏单例
if (SINGLETON_01 !=null) {
throw new RuntimeException("单例对象不能重复创建");
}
System.out.println("private Singleton01");
}
public static Singleton01 getSingleton01() {
return SINGLETON_01;
}
/**
* 通过调用静态方法,实现类的初始化
* 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
*/
public static void otherMethod() {
System.out.println("判断是懒汉式还是饿汉式");
}
}
2、反序列化破坏单例
Singleton01类要实现Serializable
package com.sofwin.singletonDemo;
import java.io.Serializable;
/**
* @packageName: com.sofwin.singletonDemo
* @author: wentao
* @date: 2022/11/21 10:00
* @version: 1.0
* @email [email protected]
* @description: 单例模式-饿汉式
*
* 要点:
* 1.构造器私有化
* 2.定义静态常量存储对象唯一实例
* 3.通过getter方法获取实例对象
*/
public class Singleton01 implements Serializable {
/**
* 构造器私有化
*/
private static final Singleton01 SINGLETON_01 = new Singleton01();
private Singleton01() {
//防止反射破坏单例
if (SINGLETON_01 !=null) {
throw new RuntimeException("单例对象不能重复创建");
}
System.out.println("private Singleton01");
}
public static Singleton01 getSingleton01() {
return SINGLETON_01;
}
/**
* 通过调用静态方法,实现类的初始化
* 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
*/
public static void otherMethod() {
System.out.println("判断是懒汉式还是饿汉式");
}
}
测试代码
package com.sofwin.singletonDemo;
import org.junit.Test;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @packageName: com.sofwin.singletonDemo
* @author: wentao
* @date: 2022/11/21 10:09
* @version: 1.0
* @email [email protected]
* @description: 单例模式的测试
*/
public class SingletonTest {
//单例模式-饿汉式
@Test
public void SinletonTest01() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
//先判断是否类初始化的时候就创建对象了
Singleton01.otherMethod();
System.out.println("=================");
Singleton01 singleton01 = Singleton01.getSingleton01();
Singleton01 singleton02 = Singleton01.getSingleton01();
System.out.println(singleton01);
System.out.println(singleton02);
// System.out.println("反射暴力破解");
// SingletonTest.reflection(Singleton01.class);
System.out.println("反序列化破解");
SingletonTest.serialzable(singleton02);
}
/**
* 反射破坏单例pos
* @param clazz 类对象
*/
public static void reflection(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取无参构造方法
Constructor declaredConstructor = clazz.getDeclaredConstructor();
//暴力破解
declaredConstructor.setAccessible(true);
//通过反射创建实例对象
Object o = declaredConstructor.newInstance();
System.out.println(o);
}
/**
* 反序列破解单例模式
* @param instance 对象
*/
public static void serialzable(Object instance) throws IOException, ClassNotFoundException {
//将对象读取到baos中
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(instance);
//通过字节数组获取对象
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
Object o = ois.readObject();
System.out.println(o);
}
}
改进
package com.sofwin.singletonDemo;
import java.io.Serializable;
/**
* @packageName: com.sofwin.singletonDemo
* @author: wentao
* @date: 2022/11/21 10:00
* @version: 1.0
* @email [email protected]
* @description: 单例模式-饿汉式
*
* 要点:
* 1.构造器私有化
* 2.定义静态常量存储对象唯一实例
* 3.通过getter方法获取实例对象
*/
public class Singleton01 implements Serializable {
/**
* 构造器私有化
*/
private static final Singleton01 SINGLETON_01 = new Singleton01();
private Singleton01() {
//防止反射破坏单例
if (SINGLETON_01 !=null) {
throw new RuntimeException("单例对象不能重复创建");
}
System.out.println("private Singleton01");
}
public static Singleton01 getSingleton01() {
return SINGLETON_01;
}
/**
* 通过调用静态方法,实现类的初始化
* 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
*/
public static void otherMethod() {
System.out.println("判断是懒汉式还是饿汉式");
}
/**
* 解决反序列化
* @return 实例对象
*
*/
public Object readResolve() {
return SINGLETON_01;
}
}
这里 readResolve() 方法的解释
简而言之,当我们通过反序列化readObejct方法获取对象的时候,会去寻找readResolve()方法,如果该方法不存在则直接返回新对象,如果该方法存在则按照该方法的内容返回对象,以确保如果我们之前实例化了单例对象,就返回该对象。
为什么要使用功能readResolve()方法就解决了?
这里看一下重点代码,readOrdinaryObject
方法的代码片段:
isInstantiable
:如果一个serializable/externalizable的类可以在运行时被实例化,那么该方法就返回true。针对serializable和externalizable我会在其他文章中介绍。
desc.newInstance
:该方法通过反射的方式调用无参构造方法新建一个对象。
然后关键是下面的代码
if (obj != null &&
handles.lookupException(passHandle) == null &&
desc.hasReadResolveMethod())
{
Object rep = desc.invokeReadResolve(obj);
if (unshared && rep.getClass().isArray()) {
rep = cloneArray(rep);
}
if (rep != obj) {
// Filter the replacement object
if (rep != null) {
if (rep.getClass().isArray()) {
filterCheck(rep.getClass(), Array.getLength(rep));
} else {
filterCheck(rep.getClass(), -1);
}
}
handles.setObject(passHandle, obj = rep);
}
}
hasReadResolveMethod
:如果实现了serializable 或者 externalizable接口的类中包含readResolve
则返回true
invokeReadResolve
:通过反射的方式调用要被反序列化的类的readResolve方法。
所以,原理也就清楚了,主要在Singleton中定义readResolve方法,并在该方法中指定要返回的对象的生成策略,就可以防止单例被破坏。
3、Unsafe破坏单例
package com.sofwin.singletonDemo;
import org.junit.Test;
import org.springframework.objenesis.instantiator.util.UnsafeUtils;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @packageName: com.sofwin.singletonDemo
* @author: wentao
* @date: 2022/11/21 10:09
* @version: 1.0
* @email [email protected]
* @description: 单例模式的测试
*/
public class SingletonTest {
//单例模式-饿汉式
@Test
public void SinletonTest01() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
//先判断是否类初始化的时候就创建对象了
Singleton01.otherMethod();
System.out.println("=================");
Singleton01 singleton01 = Singleton01.getSingleton01();
Singleton01 singleton02 = Singleton01.getSingleton01();
System.out.println(singleton01);
System.out.println(singleton02);
// System.out.println("反射暴力破解");
// SingletonTest.reflection(Singleton01.class);
// System.out.println("反序列化破解");
// SingletonTest.serialzable(singleton02);
System.out.println("unsafe");
unsafe(singleton01.getClass());
}
/**
* 反射破坏单例pos
* @param clazz 类对象
*/
public static void reflection(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取无参构造方法
Constructor declaredConstructor = clazz.getDeclaredConstructor();
//暴力破解
declaredConstructor.setAccessible(true);
//通过反射创建实例对象
Object o = declaredConstructor.newInstance();
System.out.println(o);
}
/**
* 反序列破解单例模式
* @param instance 对象
*/
public static void serialzable(Object instance) throws IOException, ClassNotFoundException {
//将对象读取到baos中
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(instance);
//通过字节数组获取对象
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
Object o = ois.readObject();
System.out.println(o);
}
/**
* 使用spring的工具类在jdk底层来访问,无序调用构造方法
* @param clazz
* @throws InstantiationException
*/
public static void unsafe(Class clazz) throws InstantiationException {
Object o = UnsafeUtils.getUnsafe().allocateInstance(clazz);
System.out.println(o);
}
}
这个是无法解决的
代码
package com.sofwin.singletonDemo;
import sun.dc.pr.PRError;
/**
* @packageName: com.sofwin.singletonDemo
* @author: wentao
* @date: 2022/11/21 11:34
* @version: 1.0
* @email [email protected]
* @description: 单例模式 --枚举饿汉式
*/
public enum Singleton02 {
INSTANCE;
private Singleton02() {
System.out.println("private Singleton02");
}
public static Singleton02 getInstance() {
return INSTANCE;
}
/**
* 通过调用静态方法,实现类的初始化
* 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
*/
public static void otherMethod() {
System.out.println("判断是懒汉式还是饿汉式");
}
@Override
public String toString() {
//Integer.toHexString 转换为16进制
return getClass().getName()+"@"+Integer.toHexString(hashCode());
}
}
测试
package com.sofwin.singletonDemo;
import org.junit.Test;
import org.springframework.objenesis.instantiator.util.UnsafeUtils;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @packageName: com.sofwin.singletonDemo
* @author: wentao
* @date: 2022/11/21 10:09
* @version: 1.0
* @email [email protected]
* @description: 单例模式的测试
*/
public class SingletonTest {
//单例模式-饿汉式
@Test
public void SinletonTest01() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
//先判断是否类初始化的时候就创建对象了
Singleton01.otherMethod();
System.out.println("=================");
Singleton02 singleton01 = Singleton02.INSTANCE;
Singleton02 singleton02 = Singleton02.INSTANCE;
System.out.println(singleton01);
System.out.println(singleton02);
//1、反射不存在,枚举没有无参构造器
// System.out.println("反射暴力破解");
// SingletonTest.reflection(Singleton02.class);
//2、反序列化不存在,readObject的时候会进行判断 ,如果是枚举类有特殊处理
// System.out.println("反序列化破解");
// SingletonTest.serialzable(singleton02);
//3、jdk这个是无法避免的,是可以破坏的
// System.out.println("unsafe");
// unsafe(singleton01.getClass());
}
/**
* 反射破坏单例pos
* @param clazz 类对象
*/
public static void reflection(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取无参构造方法
Constructor declaredConstructor = clazz.getDeclaredConstructor();
//暴力破解
declaredConstructor.setAccessible(true);
//通过反射创建实例对象
Object o = declaredConstructor.newInstance();
System.out.println(o);
}
/**
* 反序列破解单例模式
* @param instance 对象
*/
public static void serialzable(Object instance) throws IOException, ClassNotFoundException {
//将对象读取到baos中
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(instance);
//通过字节数组获取对象
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
Object o = ois.readObject();
System.out.println(o);
}
/**
* 使用spring的工具类在jdk底层来访问,无序调用构造方法
* @param clazz
* @throws InstantiationException
*/
public static void unsafe(Class clazz) throws InstantiationException {
Object o = UnsafeUtils.getUnsafe().allocateInstance(clazz);
System.out.println(o);
}
}
1、反射无法破坏枚举类单例
枚举没有无参构造
修改成有参构造
/**
* 反射破坏单例pos
* @param clazz 类对象
*/
public static void reflection(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取无参构造方法
Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class,int.class);
//暴力破解
declaredConstructor.setAccessible(true);
//通过反射创建实例对象
Object o = declaredConstructor.newInstance("OTHER",1);
System.out.println(o);
}
2、反序列话也无法破坏枚举类的单例
3、Unsafe是可以破坏的
代码
package com.sofwin.singletonDemo;
import java.io.Serializable;
/**
* @packageName: com.sofwin.singletonDemo
* @author: wentao
* @date: 2022/11/21 10:00
* @version: 1.0
* @email [email protected]
* @description: 单例模式-懒汉式
*
* 要点:
* 1.构造器私有化
* 2.定义静态常量存储对象唯一实例
* 3.通过getter方法获取实例对象
*/
public class Singleton03 implements Serializable {
/**
* 构造器私有化
*/
private static Singleton03 instance = null;
private Singleton03() {
//防止反射破坏单例
if (instance !=null) {
throw new RuntimeException("单例对象不能重复创建");
}
System.out.println("private Singleton01");
}
public static Singleton03 getSingleton01() {
if (instance == null) {
instance = new Singleton03();
}
return instance;
}
/**
* 通过调用静态方法,实现类的初始化
* 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
*/
public static void otherMethod() {
System.out.println("判断是懒汉式还是饿汉式");
}
/**
* 解决反序列化
* @return 实例对象
*
*/
public Object readResolve() {
return instance;
}
}
测试
package com.sofwin.singletonDemo;
import org.junit.Test;
import org.springframework.objenesis.instantiator.util.UnsafeUtils;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
/**
* @packageName: com.sofwin.singletonDemo
* @author: wentao
* @date: 2022/11/21 10:09
* @version: 1.0
* @email [email protected]
* @description: 单例模式的测试
*/
public class SingletonTest {
//单例模式-饿汉式
@Test
public void SinletonTest01() throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
//先判断是否类初始化的时候就创建对象了
Singleton03.otherMethod();
System.out.println("=================");
Singleton03 singleton01 = Singleton03.getSingleton01();
Singleton03 singleton02 = Singleton03.getSingleton01();
System.out.println(singleton01);
System.out.println(singleton02);
//1、反射可以破坏单例
// System.out.println("反射暴力破解");
// SingletonTest.reflection(Singleton03.class);
//2、反序列化也可以破坏
// System.out.println("反序列化破解");
// SingletonTest.serialzable(singleton02);
//3、jdk这个是无法避免的,是可以破坏的
// System.out.println("unsafe");
// unsafe(singleton01.getClass());
}
/**
* 反射破坏单例pos
* @param clazz 类对象
*/
public static void reflection(Class clazz) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//获取无参构造方法
Constructor declaredConstructor = clazz.getDeclaredConstructor();
//暴力破解
declaredConstructor.setAccessible(true);
//通过反射创建实例对象
Object o = declaredConstructor.newInstance();
System.out.println(o);
}
/**
* 反序列破解单例模式
* @param instance 对象
*/
public static void serialzable(Object instance) throws IOException, ClassNotFoundException {
//将对象读取到baos中
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(instance);
//通过字节数组获取对象
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
Object o = ois.readObject();
System.out.println(o);
}
/**
* 使用spring的工具类在jdk底层来访问,无序调用构造方法
* @param clazz
* @throws InstantiationException
*/
public static void unsafe(Class clazz) throws InstantiationException {
Object o = UnsafeUtils.getUnsafe().allocateInstance(clazz);
System.out.println(o);
}
}
反射、序列化和unsafe都可以破坏
但是这样都会导致一个问题多线程的情况会出现错误情况 (之前,懒汉式的常量和静态代码块中的代码,其实是jvm底层维护的是线程安全的,无序考虑) 因为这个是方法中创建实例就会出现线程安全的问题
测试代码
public class SingletonTest {
public static void main(String[]args){
new Thread( new Runnable() {
@Override
public void run() {
Singleton03 singleton01 = Singleton03.getSingleton01();
System.out.println(singleton01);
}
}).start();
new Thread( new Runnable() {
@Override
public void run() {
Singleton03 singleton01 = Singleton03.getSingleton01();
System.out.println(singleton01);
}
}).start();
}
}
正常应该是这种情况:
但是多运行几次,也会出现这样的情况:
造成的这种情况的结果是问题是:
这个时候就出现了DCL懒汉式(双检锁的懒汉式)
package com.sofwin.singletonDemo;
import java.io.Serializable;
/**
* @packageName: com.sofwin.singletonDemo
* @author: wentao
* @date: 2022/11/21 10:00
* @version: 1.0
* @email [email protected]
* @description: 单例模式-懒汉式
*
* 要点:
* 1.构造器私有化
* 2.定义静态常量存储对象唯一实例
* 3.通过getter方法获取实例对象
*/
public class Singleton04 implements Serializable {
/**
* 构造器私有化
*/
//这里加入valatile是保证这个变量是有序的,可见的
//防止指令重排序,在赋值语句后加入一个内存屏障,防止之前的赋值操作,进行重新排序
private static volatile Singleton04 instance = null;
private Singleton04() {
//防止反射破坏单例
if (instance !=null) {
throw new RuntimeException("单例对象不能重复创建");
}
System.out.println("private Singleton01");
}
public static Singleton04 getSingleton01() {
if (instance == null) {
synchronized (Singleton04.class){
if (instance == null) {
instance = new Singleton04();
}
}
}
return instance;
}
/**
* 通过调用静态方法,实现类的初始化
* 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
*/
public static void otherMethod() {
System.out.println("判断是懒汉式还是饿汉式");
}
/**
* 解决反序列化
* @return 实例对象
*
*/
public Object readResolve() {
return instance;
}
}
这个代码可以这样理解:
public static Singleton04 getSingleton01() {
if (instance == null) {
synchronized (Singleton04.class){
if (instance == null) {
instance = new Singleton04();
}
}
//里面这一块是进行加锁放在出现上面的情况
//外面的if判断是进行代码的优化
//我们这个线程锁只是还没创建对象实例的情况出现,因此加上if后
//我们就保证了后序的调用无需进行加锁操作,加快了效率
}
return instance;
}
package com.sofwin.singletonDemo;
import java.io.Serializable;
/**
* @packageName: com.sofwin.singletonDemo
* @author: wentao
* @date: 2022/11/21 10:00
* @version: 1.0
* @email [email protected]
* @description: 单例模式-内部类懒汉式
*
* 要点:
* 内部类不会随着玩不类的加载而初始化
* 它是单独进行初始化和加载的,并且静态成员的赋值,都是在静态代码块中的,是底层保证线程安全的
* 只有调用内部类的类变量的时候,才进行初始化,实现懒汉式模式
*/
public class Singleton05 implements Serializable {
/**
* 构造器私有化
*/
private Singleton05() {
System.out.println("private Singleton01");
}
private static class Holder {
static Singleton05 instance = new Singleton05();
}
public static Singleton05 getSingleton01() {
return Holder.instance;
}
/**
* 通过调用静态方法,实现类的初始化
* 判断实例对象是类初始化就创建了 还是调用获取实例对象的时候才进行创建
*/
public static void otherMethod() {
System.out.println("判断是懒汉式还是饿汉式");
}
}
System的gc() 垃圾回收机制中的Runtime.getRuntime().gc()
public class Runtime {
private static Runtime currentRuntime = new Runtime();
/**
* Returns the runtime object associated with the current Java application.
* Most of the methods of class Runtime
are instance
* methods and must be invoked with respect to the current runtime object.
*
* @return the Runtime
object associated with the current
* Java application.
*/
public static Runtime getRuntime() {
return currentRuntime;
}
/** Don't let anyone else instantiate this class */
private Runtime() {}
Comparator的naturalOrder()
System中的cons成员变量
Collections中的emptyListInterator()