Si mon IDE est si intelligent, pourquoi dois-je lancer «clone ()»?

13

Mon type IDE ( NetBeans ) vérifie mon Collectionspendant que je tape du code. Mais alors, pourquoi dois-je lancer l'objet retourné Object.clone()? Ce qui est bien. Pas de mal, pas de faute. Mais je ne comprends toujours pas.

La vérification de type, sans transtypage, l'objet retourné Object.clone()n'est -elle pas possible? Le cadre générique me fait penser que l'EDI pourrait vérifier le type de références d'objet sur le côté droit de la marque " = " sans transtypage pendant que je tape? Je ne comprends pas.

addendum
Mon cas d'utilisation était juste que j'avais un Calendarchamp privé , pubdate . J'allais écrire:

Calendar getPubdate() {
    return pubdate;
}

mais il y a un risque que l'invocateur puisse modifier ma publication , j'ai donc renvoyé une copie:

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

Ensuite, je me suis demandé pourquoi j'avais besoin de lancer pubdate.clone(). La signature de méthode a le type juste là. NetBeans devrait être capable de comprendre cela. Et NetBeans semblait faire quelque chose de similaire en ce qui concerne Collections.

konishiki
la source
5
Un exemple de code court (!) Serait utile.
Doc Brown
78
L'IDE est distinct du langage lui-même, donc la façon dont les Netbeans intelligents n'ont aucun effet sur le fonctionnement du langage Java.
JacquesB
7
Remarque, en raison de la covariance de type de retour, il est recommandé de revenir MyObjectde clone()plutôt que Object- cela supprime tout ce problème. Il est en outre recommandé de ne jamais l'utiliser clone()(Effective Java Item # 11).
Boris the Spider
Votre question porte-t-elle sur moi ou sur "cast" clone () "' ? Parce que la question résultant de la première pourrait en fait être une bien meilleure question que de la seconde.
user541686
Quand j'ai lu le titre de la question, la seule chose à laquelle je pense est this.clone()sur l'objet programmeur, surtout la nuit de mercredi après la sortie de Tue. Désolé , mais je dois écrire ce comment..Why ne peut pas intelligent IDE fixe simplement tous les bugs pour nous LOL
Mai

Réponses:

53

pourquoi dois-je lancer l'objet retourné Object.clone()?

Parce qu'il revient Object.

Le cadre générique me fait penser que l'EDI pourrait vérifier le type de références d'objet sur le côté droit de la marque " = " sans transtypage pendant que je tape? Je ne comprends pas.

Object.clone n'est pas générique.

Si des génériques avaient existé au moment de la cloneconception, cela aurait probablement ressemblé à ceci (en utilisant le polymorphisme F-Bounded):

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

Si Java avait une fonctionnalité MyType, cela ressemblerait peut-être à ceci:

interface Cloneable {
  this clone();
}

Mais les génériques n'existaient pas au moment de la Object.cloneconception, et Java n'a pas MyTypes, donc la version non sécurisée de type avec Object.clonelaquelle nous devons travailler.

Jörg W Mittag
la source
Je viens de réaliser que la fonctionnalité IDE qui m'a dérouté était la compilation en arrière-plan? Je veux dire, c'est ce qui permet l'achèvement du code et la vérification automatique du type avec les génériques? Personnellement, je préférerais retarder la vérification de type jusqu'à une compilation explicite. Mais j'aime la complétion de code.
konishiki
1
@konishiki avec Java 8 de type (et dans une certaine mesure Java 7) inférence , afin de fournir une aide, les besoins IDE aux types INFER. Cela nécessite une compilation partielle. Avant l'inférence de type, aucune compilation n'est nécessaire pour la saisie semi-automatique.
Boris the Spider
@BoristheSpider Merci beaucoup pour ces commentaires! J'ai vraiment besoin de faire plus de tests / réflexion. très apprécié.
konishiki
Pourquoi auriez-vous besoin de passer original?
Clashsoft
@Clashsoft: Thinko stupide lors de l'adaptation de la version de programmation fonctionnelle évidente. Merci.
Jörg W Mittag
26

Ce n'est une caractéristique d'aucun IDE, mais de la définition du langage.

Un IDE vous aide à utiliser un langage de programmation plus efficacement, il ne change pas la sémantique de ce langage. Cela signifie qu'un assistant d'édition peut insérer automatiquement un transtypage quand il est évident lequel vous voulez, mais il ne peut pas simplement enfreindre les règles du langage et prétendre que le code qui ne compile pas est valide.

Modifier Il est vrai qu'un IDE peut regrouper son propre compilateur, et en fait, beaucoup le font exactement, par exemple pour un meilleur rapport d'erreurs avec plus d'informations internes dans l'arbre d'analyse partielle. Cependant, ce serait une très mauvaise idée de laisser ce compilateur interne implémenter une sémantique de langage différente de celle du SDK officiel, car cela signifierait que le code qui fonctionne en développement peut mystérieusement commencer à échouer lorsqu'il est installé en production - produisant des problèmes par définition non débogable!

Kilian Foth
la source
C'est ce qui s'est passé: je suis presque sûr que l'achèvement du code est une fonctionnalité IDE (effectuée via la réflexion). Et la vérification automatique du type dont je parlais se produit dans l'EDI (via la compilation en arrière-plan). J'espère que c'est ce qui se passe.
konishiki
1
L'IDE peut très facilement enfreindre toutes les règles de la spécification de langue et simplement compiler le code de toute façon. Je sais que NetBeans et Eclipse utilisent leurs propres compilateurs, par exemple. Donc, dans ces cas, l'IDE et le compilateur sont effectivement la même chose. Je ne dis pas que c'est une bonne idée, mais les compilateurs C le font certainement tout le temps.
MichaelS
@MichaelS La spécification du langage C est conçue pour permettre des variations importantes entre les implémentations, afin que différents fournisseurs puissent choisir entre différentes approches possibles et ajouter des fonctionnalités supplémentaires. Cela crée diverses zones d'ambiguïté dans la spécification, qui sont nécessaires pour permettre ces variations. Le nom "C" n'est pas une marque déposée, donc personne ne contrôle l'utilisation du terme. La spécification Java est conçue pour éliminer autant d'ambiguïté que possible, et Java est une marque déposée et le titulaire de la marque impose qu'elle ne peut être utilisée que dans des implémentations conformes.
Jules
Les IDE modernes ont quand même besoin d'un compilateur. Les conseils de complétion de code nécessitent que le code avant que le curseur soit analysé. Et certainement avec des génériques (ou des modèles C ++) qui nécessitent un compilateur complet, pas seulement un analyseur.
MSalters
3

Cela est dû à la signature de type de la méthode Object.clone. La signature de type indique que la méthode retournera un objet de type Object.

protected Object clone() throws CloneNotSupportedException

Les collections utiliseront des types dits génériques pour remplacer automatiquement le type de transtypage.

Donc, si vous avez ce code:

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

le compilateur ajoutera les castes pour vous dans les coulisses, donc le code serait en fait:

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

Par souci d'exhaustivité, depuis Java 5, les types de retour covariants sont autorisés . Vous pouvez donc écrire ce qui suit:

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

Avec cela, le code suivant est légal:

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