Возможно ли поверхностное копирование объекта класса Singleton? - PullRequest
0 голосов
/ 04 июля 2018

Используя метод clone, можем ли мы получить много экземпляров класса, который был сделан singleton?

Кроме того, необходимо ли написать «реализует Cloneable», потому что я узнал, что все объекты расширяются из класса Object, и, следовательно, дочерний объект, вызывающий защищенный clone () для другого дочернего объекта Object, не должен иметь проблем с доступом

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Этого не произойдет, пока вы не реализуете Cloneable своим синглтоном (что является анти-паттерном, поскольку противоречит самой цели синглтона). Так что это может произойти, только если вы сделаете что-то вроде этого:

SomeClass.java

class SomeClass implements Cloneable {
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

Singleton.java

class Singleton extends SomeClass {
    public static Singleton instance = new Singleton();
    private Singleton() {}
}

Main.java

class Main {
    public static void main(String[] args) throws CloneNotSupportedException {
        Singleton singleton1 = Singleton.instance;
        Singleton singleton2 = singleton1.clone();
        System.out.println("singleton1 : "
                       + singleton1.hashCode());
        System.out.println("singleton2 : "
                       + singleton2.hashCode()); 
    }
}    

выход

singleton1: 445884362

singleton2: 1793329556

Даже в этом случае вы можете решить эту проблему, переопределив clone в Singleton и сгенерировав исключение.

0 голосов
/ 04 июля 2018

Во-первых, никогда не используйте клон. Смотрите здесь

Во-вторых, клон сделать мелкую копию. Смотрите здесь

И последнее, предлагаем использовать enum для singleton, что гарантируется VM. Смотрите здесь

0 голосов
/ 04 июля 2018

Java-Doc говорит о Object.clone():

Создает и возвращает копию этого объекта. Точное значение «копия» может зависеть от класса объекта.

Это зависит от вашей реализации метода clone(), какую копию или клон вы получите. Но Java-Doc говорит дальше:

По соглашению, объект, возвращаемый этим методом, должен быть независимо от этого объекта (который клонируется).

В соответствии с этим соглашением, клон будет другим независимым экземпляром чего-то, что раньше было экземпляром синглтона.

Продолжаем работать с Java-Doc:

Класс Object сам по себе не реализует интерфейс Cloneable, поэтому вызов метода clone для объекта, класс которого Object приводит к генерации исключения во время выполнения.

Итак, вы должны явно объявить, что ваш класс implements Cloneable. Пока вы этого не сделаете, в вашем экземпляре нет открытого метода clone(). Но вы не сделаете этого для синглтона, поскольку это сделает ваш дизайн класса (синглтон) бесполезным.

Если вы не объявили одноэлементный класс final и расширили его другим классом, экземпляр которого будет вызывать super.clone(), это приведет к выбросу упомянутого CloneNotSupportedException.

Если вы явно объявите, что ваш синглтон-класс implements Cloneable в соответствии с Java-Doc, это:

создает новый экземпляр класса этого объекта и инициализирует все его поля с точно содержимым соответствующих полей этот объект как бы по заданию; содержимое полей не сами клонировали. Таким образом, этот метод выполняет "мелкую копию" этого объект, а не операция "глубокого копирования".

Чтобы получить правильный клон, Java-Doc Cloneable говорит:

... классы, которые реализуют этот интерфейс, должны переопределять Object.clone ... Следовательно, невозможно клонировать объект только в силу того факта, что он реализует этот интерфейс.

Так что вам действительно нужно это сделать явно .


Отвечая на вопрос:
Является ли это возможным? Да, но только если вы позволите.
Это предназначено? Нет.

Также обратите внимание:
Помимо упомянутого выше, используя отражение, вы можете попытаться обойти ограничения видимости одноэлементного класса для создания дополнительных экземпляров.

...