Если моя IDE такая умная, зачем мне приводить «clone ()»?

13

Мой тип IDE ( NetBeans ) проверяет мой, Collectionsпока я набираю код. Но тогда, почему я должен бросить возвращенный объект Object.clone()? Что хорошо. Нет вреда, нет фола. Но все же я не понимаю.

Является ли проверка типов без приведения возвращаемого объекта Object.clone()невозможной? Дженерики структура заставляет меня думать IDE может проверить тип ссылок на объекты на правой стороне « = марки» без литья в то время как я печатаю? Я не понимаю

Приложение
Мой случай использования состоял в том, что у меня было личное Calendarполе, pubdate . Я собирался написать:

Calendar getPubdate() {
    return pubdate;
}

но есть риск, что вызывающий может изменить мою публикацию , поэтому я вернул копию:

Calendar getPubdate() {
    return (Calendar) pubdate.clone();
}

Затем я удивился, почему мне нужно было сыграть pubdate.clone(). Подпись метода имеет тип прямо здесь. NetBeans должен быть в состоянии понять это. И NetBeans, похоже, делал что-то подобное в отношении Collections.

Konishiki
источник
5
Краткий (!) Пример кода был бы полезен.
Док Браун
78
Среда IDE отделена от самого языка, поэтому то, как интеллектуальные Netbeans не влияют на работу языка Java.
JacquesB
7
Обратите внимание, что из-за ковариации возвращаемого типа рекомендуется возвращаться MyObjectс, clone()а не с Object- это устраняет всю эту проблему. Кроме того, рекомендуется никогда не использовать clone()(Эффективный элемент Java # 11).
Борис Паук
Делается ли акцент на вашем вопросе на I или «cast» clone () » ? Потому что вопрос, вытекающий из первого, на самом деле может быть гораздо лучше, чем из второго.
user541686
Когда я читаю заголовок вопроса, единственное, о чем я думаю, - это this.clone()объект программиста, особенно ночью Ср после выхода Ту. Извините, но я должен написать этот комментарий .. Почему умная IDE не может просто исправить все ошибки для нас LOL
Mai

Ответы:

53

почему я должен бросить возвращенный объект Object.clone()?

Потому что это возвращается Object.

Дженерики структура заставляет меня думать IDE может проверить тип ссылок на объекты на правой стороне « = марки» без литья в то время как я печатаю? Я не понимаю

Object.clone не является общим.

Если бы дженерики существовали, когда они cloneбыли разработаны, это, вероятно, выглядело бы так (используя F-ограниченный полиморфизм):

interface Cloneable<T extends Cloneable<T>> {
  T clone();
}

Если бы в Java была функция MyType, она могла бы выглядеть так:

interface Cloneable {
  this clone();
}

Но Generics не существовало, когда она Object.cloneбыла разработана, и у Java нет MyTypes, поэтому Object.cloneнам приходится работать с небезопасной версией типа .

Йорг Миттаг
источник
Я только что понял, что особенность IDE, которая меня смутила, это фоновая компиляция? Я имею в виду, что это позволяет выполнять автозавершение кода и автоматическую проверку типов с помощью обобщений? Лично я предпочел бы отложить проверку типов до явной компиляции. Но я люблю завершение кода.
конишики
1
@konishiki с Java 8 (и в некоторой степени Java 7) тип логического вывода , с тем чтобы обеспечить любую помощь, потребности IDE для типов Infer. Это требует частичной компиляции. Перед выводом типа для автозаполнения компиляция не требуется.
Борис Паук
@BoristheSpider Большое спасибо за этот отзыв! Я определенно должен сделать еще несколько тестов / размышлений. очень ценится.
конишики
Зачем вам нужно пройти original?
Clashsoft
@Clashsoft: Глупое мышление при адаптации очевидной версии функционального программирования. Благодарю.
Йорг Миттаг
26

Это не особенность какой-либо IDE, но определение языка.

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

Редактировать Это правда, что IDE может связывать свой собственный компилятор, и на самом деле многие делают именно это, например, для лучшего сообщения об ошибках с большей внутренней информацией в частичное дерево разбора. Однако было бы очень плохой идеей позволить этому внутреннему компилятору реализовывать семантику языка, отличную от официального SDK, поскольку это означало бы, что код, работающий в разработке, может таинственным образом начать сбой при установке в производство, что порождает проблемы, которые по определению не отладка!

Килиан Фот
источник
Вот что произошло: я почти уверен, что завершение кода является функцией IDE (сделано с помощью отражения). А автоматическая проверка типов, о которой я говорил, происходит в IDE (с помощью фоновой компиляции). Я надеюсь, что это то, что происходит.
конишики
1
IDE может очень легко нарушить все правила языковой спецификации и просто скомпилировать код в любом случае. Я знаю, что и NetBeans, и Eclipse используют свои собственные компиляторы, например. Так что в этих случаях IDE и компилятор - это одно и то же. Не сказать, что это хорошая идея, но компиляторы C, безусловно, делают это постоянно.
MichaelS
@MichaelS Спецификация языка C предназначена для значительных различий между реализациями, так что разные поставщики могут выбирать между различными возможными подходами и добавлять дополнительные функции. Это создает различные области неоднозначности в спецификации, которые необходимы для разрешения этих изменений. Название «С» не является торговой маркой, поэтому никто не контролирует использование этого термина. Спецификация Java разработана для устранения как можно большей неопределенности, а Java является торговой маркой, а владелец торговой марки обеспечивает ее использование только в совместимых реализациях.
Жюль
Современные IDE все равно нуждаются в компиляторе. Подсказки по завершению кода требуют, чтобы код перед анализом курсора. И, конечно, с обобщениями (или шаблонами C ++), для которых требуется полный компилятор, а не просто парсер.
MSalters
3

Это связано с сигнатурой типа метода Object.clone. Сигнатура типа утверждает, что метод вернет объект типа Object.

protected Object clone() throws CloneNotSupportedException

Коллекции будут использовать так называемые универсальные типы для автоматической замены типа приведения.

Так что, если у вас есть этот код:

List<Integer> ints = Arrays.asList(1,2,3);
int x = ints.get(0);`

компилятор добавит приведенные для вас закулисные действия, поэтому код будет на самом деле:

List ints = Arrays.asList(1,2,3);
int x = (Integer)ints.get(0);
Miro
источник
0

Для полноты, начиная с Java 5, допускаются ковариантные возвращаемые типы . Таким образом, вы можете написать следующее:

public MyObject implements Cloneable {
  @Override
  public MyObject clone() {
    try {
      return (MyObject)super.clone();
    } catch (CloneNotSupportedException e) {
      throw new AssertionError();
    }
  }
}

При этом допустим следующий код:

MyObject original = new MyObject();
MyObject clone = original.clone();
Оливье Грегуар
источник