Доступ к clone() из java.lang.Object

Вот что я не могу понять.

В java.lang.Object параметр clone() определяется с помощью модификатора protected. По определению, к которому он может обращаться по имени внутри собственного определения класса, по имени внутри любого производного от него класса и по имени в определении любого класса в одном пакете.

Здесь класс Sample находится в другом пакете и, очевидно, он не может получить доступ к clone() из класса Object. Но поскольку Sample выводится неявно из Object, почему он не может получить к нему доступ? В определении не сказано, что он должен удовлетворять обоим условиям (внутри того же пакета И также быть подклассом).

public class Sample {

  public Object foo() throws CloneNotSupportedException {
   ... 
   return someObject.clone();
  }
}

Ответ 1

В вашем случае метод clone() не отображается, потому что вы не вызываете его из подкласса. Sample происходит от Object, поэтому он может получить доступ к собственному методу clone(), но не к другим объектам.

Объект clone() был разработан с несколькими ошибками. Поэтому использовать его не рекомендуется - это очень сложно сделать правильно:

  • предполагается, что не каждый объект клонируется по умолчанию
  • если вы переопределите clone(), сделав его общедоступным, он все равно будет терпеть неудачу, потому что каждый класс должен реализовать Cloneable
  • Cloneable, однако, не определяет какие-либо методы, поэтому пользователи объектов не могут ссылаться на него как Cloneable и ожидать метода клонирования.
  • каждый класс в иерархии должен вызывать super.clone() для работы механизма клонирования по умолчанию

Отметьте этот вопрос для альтернатив.

Ответ 2

Работает для меня: http://ideone.com/eST8Y

import java.util.*;
import java.lang.*;

class Main
{
    public Object foo() throws CloneNotSupportedException
    {
        return this.clone();
    }

    public static void main (String[] args) throws java.lang.Exception
    {
        new Main().foo();
    }
}

Он компилируется без ошибок. Он по-прежнему запускает среду выполнения CloneNotSupportedException, потому что Main не реализует Cloneable.

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

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


@Bozho answer - это действительно правильный ответ. Просто не используйте Object.clone().

См. Эффективная Java, пункт 10: разумно переопределить clone (пункт 11 в последующих выпусках).

Ответ 3

Здесь важен тип класса someObject. Объект someObject не может переопределять метод clone() класса Object, поэтому создание невидимо для класса Sample.

Ответ 4

Что значит "не иметь доступа к нему"? Вы имеете в виду, что он не будет компилироваться или вы имеете в виду, что он вызывает исключение CloneNotSupportedException.

Object.clone() будет бросать CloneNotSupportedException, если ваш класс не реализует интерфейс Cloneable.