Se meu IDE é tão inteligente, por que preciso converter "clone ()"?

13

Meu tipo de IDE ( NetBeans ) verifica meu Collectionscódigo enquanto estou digitando. Mas então, por que tenho que lançar o objeto retornado Object.clone()? O que é bom. Nenhum dano, nenhuma falta. Mas ainda assim, eu não entendo.

A verificação de tipo, sem conversão, o objeto retornado Object.clone()não é possível? A estrutura de genéricos me faz pensar que o IDE poderia verificar o tipo de referência de objeto no lado direito da marca " = " sem transmitir enquanto estou digitando? Eu não entendo.

adendo
Meu caso de uso foi justamente porque eu tinha um Calendarcampo privado , pubdate . Eu ia escrever:

Calendar getPubdate() {
    return pubdate;
}

mas existe o risco de o invocador poder modificar meu pubdate , então retornei uma cópia:

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

Então, eu me perguntava por que eu precisava lançar pubdate.clone(). A assinatura do método tem o tipo ali. O NetBeans deve ser capaz de descobrir isso. E o NetBeans parecia estar fazendo algo semelhante em relação a Collections.

konishiki
fonte
5
Um exemplo de código curto (!) Seria útil.
Doc Brown
78
O IDE é separado da própria linguagem, portanto, como o Netbeans é inteligente não afeta o funcionamento da linguagem Java.
JacquesB
7
Observe que, devido à covariância do tipo de retorno, é recomendável retornar MyObjectem clone()vez de Object- isso remove todo esse problema. Além disso, é recomendável nunca usar clone()(Item efetivo 11 do Java).
Boris the Spider
A ênfase da sua pergunta está em I ou em 'cast "clone ()"' ? Porque a pergunta resultante da primeira pode realmente ser uma pergunta muito melhor do que a última.
user541686
Quando leio o título da pergunta, a única coisa em que penso é this.clone()no objeto programador, especialmente na noite de Wed após o lançamento de Tue. Desculpe, mas eu tenho que escrever este comment..Why pode IDE não é inteligente apenas corrige todos os erros para nós LOL
Mai

Respostas:

53

por que eu tenho que converter o objeto retornado Object.clone()?

Porque ele retorna Object.

A estrutura de genéricos me faz pensar que o IDE poderia verificar o tipo de referência de objeto no lado direito da marca " = " sem transmitir enquanto estou digitando? Eu não entendo.

Object.clone não é genérico.

Se os genéricos existissem quando cloneforam projetados, provavelmente seria assim (usando o polimorfismo com limite de F):

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

Se o Java tivesse um recurso MyType, talvez fosse assim:

interface Cloneable {
  this clone();
}

Mas os genéricos não existiam quando Object.cloneforam projetados e o Java não possui MyTypes; portanto, Object.cloneé com a qual devemos trabalhar a versão não segura do tipo .

Jörg W Mittag
fonte
Acabei de perceber que o recurso IDE que me confundia era a compilação em segundo plano? Quero dizer, é isso que permite o preenchimento de código e a verificação automática de tipo com genéricos? Pessoalmente, eu preferiria atrasar a verificação de tipo até uma compilação explícita. Mas eu amo a conclusão de código.
Konishiki
1
@konishiki com inferência de tipo Java 8 (e até certo ponto Java 7) , para fornecer qualquer assistência, o IDE precisa inferir tipos. Isso requer compilação parcial. Antes da inferência de tipo, nenhuma compilação é necessária para o preenchimento automático.
Boris the Spider
@BoristheSpider Muito obrigado por esse feedback! Eu definitivamente preciso fazer mais alguns testes / pensamentos. muito apreciado.
Konishiki
Por que você precisaria passar original?
Clashsoft
@ Clashsoft: Thinko estúpido ao adaptar a versão óbvia da Programação Funcional. Obrigado.
Jörg W Mittag 15/03
26

Este não é um recurso de nenhum IDE, mas da definição de linguagem.

Um IDE ajuda você a usar uma linguagem de programação com mais eficiência, não altera a semântica dessa linguagem. Isso significa que um ajudante de editor pode inserir automaticamente uma conversão quando for óbvio qual você deseja, mas não pode simplesmente quebrar as regras da linguagem e fingir que o código que não compila é válido.

Editar É verdade que um IDE pode agrupar seu próprio compilador e, de fato, muitos fazem exatamente isso, por exemplo, para obter melhores relatórios de erros com mais informações internas na árvore de análise parcial. No entanto, seria uma péssima idéia permitir que esse compilador interno implemente semântica de idioma diferente do SDK oficial, pois isso significaria que o código que funciona no desenvolvimento pode misteriosamente começar a falhar quando instalado na produção - produzindo problemas que, por definição, são debuggable!

Kilian Foth
fonte
Foi o que aconteceu: tenho certeza de que a conclusão do código é um recurso do IDE (feito via reflexão). E a verificação automática de tipo de que eu estava falando acontece no IDE (através da compilação em segundo plano). Espero que seja isso que esteja acontecendo.
Konishiki
1
O IDE pode facilmente quebrar todas as regras da especificação de idioma e compilar o código de qualquer maneira. Eu sei que o NetBeans e o Eclipse usam seus próprios compiladores, por exemplo. Portanto, nesses casos, IDE e compilador são efetivamente a mesma coisa. Não é uma boa ideia, mas os compiladores C certamente fazem isso o tempo todo.
Michaels
@MichaelS A especificação da linguagem C foi projetada para permitir variações significativas entre implementações, para que diferentes fornecedores possam escolher entre diferentes abordagens possíveis e adicionar recursos extras. Isso cria várias áreas de ambiguidade na especificação, necessárias para permitir essas variações. O nome "C" não é marca registrada, portanto ninguém controla o uso do termo. A especificação Java foi projetada para eliminar o máximo de ambiguidade possível, e Java é marca registrada e o proprietário da marca registrada reforça que ela só pode ser usada em implementações compatíveis.
Jules
Os IDE modernos precisam de um compilador de qualquer maneira. As dicas de preenchimento de código exigem que o código antes do cursor seja analisado. E certamente com genéricos (ou modelos C ++) que exigem um compilador completo, não apenas um analisador.
MSalters 16/03/16
3

Isso ocorre devido à assinatura de tipo do método Object.clone. A assinatura de tipo indica que o método retornará um objeto do tipo Object.

protected Object clone() throws CloneNotSupportedException

As coleções usarão os chamados tipos genéricos para substituir automaticamente o tipo de conversão.

Então, se você tem este código:

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

o compilador adicionará os lançamentos para você nos bastidores, para que o código seja realmente:

List ints = Arrays.asList(1,2,3);
int x = (Integer)ints.get(0);
Miro
fonte
0

Para ser completo, desde o Java 5, tipos de retorno covariantes são permitidos . Então você pode escrever o seguinte:

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

Com isso, o seguinte código é legal:

MyObject original = new MyObject();
MyObject clone = original.clone();
Olivier Grégoire
fonte