2010-10-15 6 views
3

Ce code:java: comment utiliser clone() et quid du contrôle cast

class RawStringIterator { 
     java.util.Stack<State> stateStack = new java.util.Stack<State>(); 
     RawStringIterator(RawStringIterator i) { 
       stateStack = (java.util.Stack<State>) i.stateStack.clone(); 
     } 
     /* ... */ 
} 

me donne cet avertissement:

Type safety: Unchecked cast from Object to Stack<Utils.OperatorTree.RawStringIterator.State> 

Je suppose que je peux ignorer l'avertissement ici. Mais je me demande comment utiliser clone() en général? Dois-je toujours utiliser un @SuppressWarnings("unchecked") chaque fois que j'utilise clone()? Ou devrais-je toujours faire le contrôle supplémentaire complètement redondant?

Répondre

11

Si vous avez le choix, le meilleur n'est pas pour mettre en œuvre/utiliser clone() du tout, car it is a broken API. Implémentez/utilisez simplement un constructeur de copie à la place.

Si pour une raison impérieuse vous devez utiliser clone() mais peut changer sa mise en œuvre, d'envisager de proclamer Stack<T>.clone() retourner Stack<T> au lieu de Object - types de retour covariants sont légales depuis Java5.

Mise à jour: si le Stack en question est java.util.Stack, tenez compte its Javadoc:

Un ensemble plus complète et cohérente des opérations de la pile LIFO est fournie par l'interface Deque et ses mises en œuvre, qui devrait être utilisé dans préférence à cette classe.

Et par ex. ArrayDeque fournit un copy constructor.

+0

'Stack ' est 'java.util.Stack ' ici. Donc, je ne peux pas vraiment changer une déclaration là-bas. – Albert

+0

@Albert, vous pouvez toujours être en mesure de passer à une collection différente si - voir ma mise à jour. –

+0

+1 pour 'Deque'. – Bozho

0

Vous avez très peu de choix mais de l'ignorer.

Bien que pas directement pertinent (parce que vous n'êtes pas d'écrire une méthode clone()), cette entrée dans la Java Generics FAQ fait bonne lecture (tout comme toute la FAQ!)

2

Il n'y a aucun moyen d'éviter la distribution ici. clone() renvoie Object, s'il est java.util.Stack, il n'utilise pas les types de retour co-variant.

Si ce n'est pas java.util.Stack, alors ne pas implémenter clone() - c'est vraiment difficile de bien faire les choses. Créez un constructeur de copie à la place. Oui, vous devrez supprimer explicitement les avertissements chaque fois que vous utiliserez clone().

+0

Vous pouvez (et il est recommandé d'utiliser) des types de retour covariant avec votre 'clone()' - Java efficace 2nd Ed. Le point 11 montre des exemples explicites. –

+0

oui, mais pas java.util.Stack. C'était mon point. Je vais clarifier – Bozho

+0

Non, 'java.util.Stack' n'a pas de constructeur de copie. Sinon, je l'aurais utilisé. – Albert

0

C'est l'une des raisons pour lesquelles vous préféreriez utiliser des constructeurs de copie au lieu de clone(), si disponible.

Soit dit en passant dans votre code, lorsque le constructeur RawStringIterator(RawStringIterator i) est utilisé, la première initialisation de stateStack est inutile:

class RawStringIterator { 
    Stack<State> stateStack = new Stack<State>(); 
    RawStringIterator(RawStringIterator i) { 
      stateStack = (Stack<State>) i.stateStack.clone(); 
    } 
    /* ... */ 
} 

Vous pouvez supprimer cela.