绝对不能创建第二个对象的设计模式

解决方案 »

  1.   

    这个是不能自己调用创建的,可以调用instance()方法返回
      

  2.   

    这个是不能自己调用创建的,可以调用instance()方法返回我知道单例模式不是自己 new 对象,但是你的代码里调用 getInstance 也一样会出错
      

  3.   

    这个是不能自己调用创建的,可以调用instance()方法返回class Single {

    private static Single instance;

    static {
    try{
    new InitError();
    }catch(Throwable t){
    t.printStackTrace();
    }
    }

    public static Single instance(){
    return instance;
    }

    public Single(){
    InitError.o.fun();
    }

    private static class InitError {
    static InitError o = new InitError();

    static {
    Single.instance = new Single();
    throwError();
    }

    static void throwError(){
    throw new IllegalAccessError();
    }

    void fun(){
    }
    }
    }public class Test9 { public static void main(String[] args){
    Single s1 = Single.instance();
    System.out.println(s1.getClass().getName());
    }
    }java.lang.IllegalAccessError
    com.idbk.ismart.java.demo.Single
    at com.idbk.ismart.java.demo.Single$InitError.throwError(Test9.java:32)
    at com.idbk.ismart.java.demo.Single$InitError.<clinit>(Test9.java:28)
    at com.idbk.ismart.java.demo.Single.<clinit>(Test9.java:9)
    at com.idbk.ismart.java.demo.Test9.main(Test9.java:43)
      

  4.   

    简单的不让创建再二次对象的方式可以这样
    设置私有构造器,这样不会被使用者通过 new 来创建,然后一个 public final 的属性并且赋个初值
    class MySingle {

    public static final MySingle instance = new MySingle();

    private MySingle(){
    if(instance != null)
    throw new RuntimeException("只能创建一个对象");
    else
    System.out.println("第一次创建对象!");
    }
    }
    但是,java 支持反射(C#也支持反射),有了反射就可以绕过一些限制访问类的成员,以下代码可以在单例模式下创建多个对象
    class MySingle {

    public static final MySingle instance = new MySingle();

    private MySingle(){
    if(instance != null)
    throw new RuntimeException("只能创建一个对象");
    else
    System.out.println("第一次创建对象!");
    }
    }public class Test9 { public static void main(String[] args) throws Exception {
    // Single s1 = Single.instance();
    // System.out.println(s1.getClass().getName());

    try{
    MySingle obj1 = MySingle.instance;
    System.out.println(obj1.getClass().getName());
    }catch(Exception ex){
    ex.printStackTrace();
    }

    try{
    // 利用反射调用类的私有构造器(失败)
    Class<? extends MySingle> cls = MySingle.class;
    java.lang.reflect.Constructor<? extends MySingle> constructor = cls.getDeclaredConstructor();
    constructor.setAccessible(true);
    MySingle obj2 = constructor.newInstance();
    System.out.println(obj2.getClass().getName());
    }catch(Exception ex){
    ex.printStackTrace();
    }

    try{
    // 利用反射清除 MySingle.instance值,然后再次利用反射调用类构造器
    Class<? extends MySingle> cls = MySingle.class;
    java.lang.reflect.Field instanceField = cls.getDeclaredField("instance");
    instanceField.setAccessible(true);
    // 先清除 instance 的 final 属性
    java.lang.reflect.Field modifierField = java.lang.reflect.Field.class.getDeclaredField("modifiers");
    modifierField.setAccessible(true);
    modifierField.set(instanceField, instanceField.getModifiers() & ~java.lang.reflect.Modifier.FINAL);

    instanceField.set(null, null);
    java.lang.reflect.Constructor<? extends MySingle> constructor = cls.getDeclaredConstructor();
    constructor.setAccessible(true);
    MySingle obj3 = constructor.newInstance();
    System.out.println(obj3.getClass().getName());

    }catch(Exception ex){
    ex.printStackTrace();
    }
    }
    }
      

  5.   

    绝对单例设计可以使用enum
      

  6.   

    这个是不能自己调用创建的,可以调用instance()方法返回class Single {

    private static Single instance;

    static {
    try{
    new InitError();
    }catch(Throwable t){
    t.printStackTrace();
    }
    }

    public static Single instance(){
    return instance;
    }

    public Single(){
    InitError.o.fun();
    }

    private static class InitError {
    static InitError o = new InitError();

    static {
    Single.instance = new Single();
    throwError();
    }

    static void throwError(){
    throw new IllegalAccessError();
    }

    void fun(){
    }
    }
    }public class Test9 { public static void main(String[] args){
    Single s1 = Single.instance();
    System.out.println(s1.getClass().getName());
    }
    }java.lang.IllegalAccessError
    com.idbk.ismart.java.demo.Single
    at com.idbk.ismart.java.demo.Single$InitError.throwError(Test9.java:32)
    at com.idbk.ismart.java.demo.Single$InitError.<clinit>(Test9.java:28)
    at com.idbk.ismart.java.demo.Single.<clinit>(Test9.java:9)
    at com.idbk.ismart.java.demo.Test9.main(Test9.java:43)上面的错误已经捕获,你的程序并没有终止,获取的单列可以使用