Как построить не Инстанцируемый и не наследуемый класс в Java

вопрос говорит все. Я знаю, что одноэлементный шаблон (с final для его класса) является решением. Есть ли какие-либо другие возможные пути достижения этой цели? Реферирование класс делает им non-инстанцируемая. Сделать его окончательным делает его не наследуемым. Как совместить то и другое?

public final class SingletonObject
{
  private SingletonObject()
  {
    // no code req'd
  }

  /*public static SingletonObject getSingletonObject()
  {
    if (ref == null)
        // it's ok, we can call this constructor
        ref = new SingletonObject();        
    return ref;
  }*/

  public Object clone()
    throws CloneNotSupportedException
  {
    throw new CloneNotSupportedException(); 
    // that'll teach 'em
  }

  private static SingletonObject ref;
}

Код Ref:http://www.javacoffeebreak.com/articles/designpatterns/index.html

3 ответов


конструктор private:

public final class Useless {
    private Useless() {}
}

частный конструктор является обычным объектно-ориентированным решением. Однако по-прежнему можно было бы создать экземпляр такого класса с помощью отражения, например:

Constructor<Useless> con = Useless.class.getDeclaredConstructor();
con.setAccessible(true); // bypass "private"
Useless object = con.newInstance();

чтобы предотвратить даже отражение от работы, бросьте исключение из конструктора:

public final class Useless {
    private Useless() {
        throw new UnsupportedOperationException();
    }
}

вы имеете в виду класс только со статическими методами? Класс не может быть одновременно окончательным и абстрактным. Но вы можете использовать собственный конструктор так, чтобы он не instantinable.

final class StaticOnly {

    private StaticOnly() {
        throw new RuntimeException("Do not try to instantiate this");
    }

    public static String getSomething() {
       return "something";
    }
}

ниже пример будет работать. Вы не создадите его, потому что оно абстрактно. Вы не унаследуете его, потому что нет способа вызвать super constructor из внешнего подкласса (будет работать только внутренний подкласс)

abstract class StaticOnly {

    private StaticOnly() {}

    public static String getSomething() {
         return "something";
    }
}

перечисление тоже будет работать

enum StaticOnly {
    S;

    public static String getSomething() {
        return "something";
    }
}

но у него всегда есть хотя бы один экземпляр (здесь это S).


Я бы использовал самый простой паттерн Singleton

enum Singleton {
    INSTANCE;
}

на enum type не является экземпляром и не наследуется, а инициализация классов является ленивой и потокобезопасной.