【发布时间】:2011-05-19 06:05:39
【问题描述】:
请注意,我已经完成了以下线程:
What is an efficient way to implement a singleton pattern in Java?
总而言之,在编写单例时有一些重要的注意事项:
- 多线程访问不得导致多个实例
- 如果单例可序列化,则必须确保反序列化不会创建新实例
- 在反射攻击的情况下,必须抛出异常/错误。
现在,正如上面线程中所提到的,使用枚举来创建单例可以确保上面提到的所有 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 点,我会很高兴!
【问题讨论】: