gpt4 book ai didi

java - 在 Java 中实现单例

转载 作者:搜寻专家 更新时间:2023-11-01 00:52:50 24 4
gpt4 key购买 nike

请注意,我已经完成了以下线程:

What is an efficient way to implement a singleton pattern in Java?

总而言之,在编写单例时有一些重要的考虑因素:

  1. 多线程访问不能导致多个实例
  2. 单例,如果可序列化,必须确保反序列化不会创建新实例
  3. 在反射攻击的情况下,必须抛出异常/错误。

现在,正如上述线程中提到的,使用枚举创建单例可确保上述所有 3 点。

下面是我写的示例代码

/*Singleton class using enum*/
package com.java.patterns;

public enum MemoryTasks {

INSTANCE;

public void performScheduleTasks(){
System.out.println("In performScheduleTasks().");
}

private MemoryTasks(){
System.out.println("In private constructor."+this.hashCode());
}

public int returnHashCodeOfInstance(){
return INSTANCE.hashCode();
}
}

/*Class to access private constructor of the Singleton*/
package com.java.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;

import com.java.patterns.MemoryTasks;

public class LaunchReflection {

public static void main(String[] args) {
launchRelectionAttack();
}

public static void launchRelectionAttack(){
Class vulnClass = null;
Constructor [] vulClassConstr = null;
Type [] vulClassConstrParamTypes = null;

try {
vulnClass = Class.forName("com.java.patterns.MemoryTasks");
vulClassConstr = vulnClass.getDeclaredConstructors();

for(Constructor constr : vulClassConstr){
vulClassConstrParamTypes = constr.getGenericParameterTypes();
System.out.println("Modifier private ? "+Modifier.isPrivate(constr.getModifiers()));
}

/*for(Type paramType : vulClassConstrParamTypes){
System.out.println(paramType.toString());
}*/
System.out.println(MemoryTasks.INSTANCE.returnHashCodeOfInstance());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

/*Class to write the enum to a file*/
package com.java.io.serialize;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

import com.java.patterns.MemoryTasks;

public class ObjectWriter {

public static void main(String[] args) {
try {
writeSerObjectToFile();
} catch (IOException e) {
e.printStackTrace();
}
}

private static void writeSerObjectToFile() throws IOException {

File file = null;
FileOutputStream fos = null;
ObjectOutputStream oos = null;

file = new File("D:/Omkar/Dump/SerObj");

try{

if(!file.exists()){
file.createNewFile();
}
fos = new FileOutputStream(file);
oos = new ObjectOutputStream(fos);

oos.writeObject(MemoryTasks.INSTANCE);

}catch(IOException e){
e.printStackTrace();
}
finally{
oos.close();
fos.close();
}
}
}

/*Class to read the serialized enum from file*/
package com.java.io.serialize;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;

import com.java.patterns.MemoryTasks;

public class ObjectRead {

public static void main(String[] args) {
readSerObjFromFile();
}

private static void readSerObjFromFile() {
File file = null;
FileInputStream fis = null;
ObjectInputStream ois = null;

file = new File("D:/Omkar/Dump/SerObj");

try {
fis = new FileInputStream(file);
if(fis.available() > 0){
ois = new ObjectInputStream(fis);

MemoryTasks instance = (MemoryTasks) ois.readObject();
System.out.println("Reading from serialised file : "+instance.returnHashCodeOfInstance());
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}

如果我能解释第 2 点和第 3 点是如何确保的,我会很高兴!

最佳答案

这两者都由 Java 语言规范保证:

The final clone method in Enum ensures that enum constants can never be cloned, and the special treatment by the serialization mechanism ensures that duplicate instances are never created as a result of deserialization. Reflective instantiation of enum types is prohibited. Together, these four things ensure that no instances of an enum type exist beyond those defined by the enum constants.

更多细节可以从http://docs.oracle.com/javase/7/docs/platform/serialization/spec/serial-arch.html#6469中找到和 java.lang.reflect API .

第 2 条:单例,如果可序列化,必须确保反序列化不会创建新实例 由枚举序列化规范保证。

Enum constants are serialized differently than ordinary serializable or externalizable objects. The serialized form of an enum constant consists solely of its name; field values of the constant are not present in the form. To serialize an enum constant, ObjectOutputStream writes the value returned by the enum constant's name method. To deserialize an enum constant, ObjectInputStream reads the constant name from the stream; the deserialized constant is then obtained by calling the java.lang.Enum.valueOf method, passing the constant's enum type along with the received constant name as arguments. Like other serializable or externalizable objects, enum constants can function as the targets of back references appearing subsequently in the serialization stream.

The process by which enum constants are serialized cannot be customized: any class-specific writeObject, readObject, readObjectNoData, writeReplace, and readResolve methods defined by enum types are ignored during serialization and deserialization.

第 3 条:在反射攻击的情况下,必须抛出异常/错误。

通过newInstance 方法创建新实例注定会失败:

IllegalArgumentException ... if this constructor pertains to an enum type.

关于java - 在 Java 中实现单例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6054495/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com