une - methode arraylist java




Pourquoi Java vous permet-il de lancer une collection? (2)

Ce n'est pas parce qu'ils sont des classes de collection, mais parce qu'ils sont des interfaces . Foo ne les met pas en œuvre, mais des sous-classes le pourraient. Ce n'est donc pas une erreur de compilation, car ces méthodes peuvent être valables pour des sous-classes. Au moment de l'exécution , s'il ne s'agit pas d'une classe qui implémente ces interfaces, il s'agit naturellement d'une erreur d'exécution.

Si vous modifiez List<String> en ArrayList<String> , vous obtiendrez également une erreur de compilation, car une sous-classe Foo peut implémenter List , mais ne peut pas étendre ArrayList (car Foo ne le fait pas). De même, si vous rendez Foo final , le compilateur vous indiquera une erreur pour vos conversions d'interface car il sait qu'elles ne peuvent jamais être vraies (puisque Foo ne peut pas avoir de sous-classes et n'implémente pas ces interfaces).

Cette question a déjà une réponse ici:

J'ai une simple classe de foo et je peux transtyper une interface de collection ( Map ou List ) sans erreur de compilation. Notez que la classe Foo n'implémente aucune interface et ne prolonge aucune autre classe.

public class Foo {

    public List<String> getCollectionCast() {
        return (List<String>) this;    // No compiler error
    }

    public Map<String, String> getCollection2Cast() {
        return (Map<String, String>) this;    // No compiler error
    }

    public Other getCast() {
        return (Other)this;     // Incompatible types. Cannot cast Foo to Other
    }

    public  static class Other {
        // Just for casting demo
    }

}

Pourquoi le compilateur Java ne renvoie-t-il pas d'erreur de types incompatibles lorsque j'essaie de convertir la classe Foo en une collection?

Foo n'implémente pas Collection . Je m'attendrais à une erreur de types incompatibles, car, compte tenu de la signature actuelle de la classe Foo , il ne peut s'agir d'une Collection .


Le compilateur n'empêche pas le code de transtyper un type vers une interface, sauf s'il peut établir avec certitude que la relation est impossible.

Si le type de cible est une interface, cela a du sens, car une classe qui étend Foo peut implémenter Map<String, String> . Cependant, notez que cela ne fonctionne que parce que Foo n'est pas final . Si vous déclariez votre classe avec la classe final class Foo , cette distribution ne fonctionnerait pas.

Si le type de cible est une classe, dans ce cas, il échouerait simplement (essayez (HashMap<String, String>) this ), car le compilateur sait avec certitude que la relation entre Foo et HashMap est impossible.

Pour référence, ces règles sont décrites dans JLS-5.5.1 (T = type de cible - Map<String, String> , S = type de source - Foo )

Si T [type de cible] est un type d'interface:

  • Si S n'est pas une classe finale (§8.1.1), alors, s'il existe un supertype X de T et un supertype Y de S, tels que X et Y soient des types paramétrés manifestement distincts, et que les effacements de X et Y sont identiques, une erreur de compilation se produit.
    Sinon, la conversion est toujours légale au moment de la compilation (car même si S n’implémente pas T, une sous-classe de S peut l’être).

  • Si S est une classe finale (§8.1.1), alors S doit implémenter T, sinon une erreur de compilation survient.

Notez le commentaire en gras et en italique dans le texte cité.





casting