2010-11-23 6 views
12

Jetez un oeil à ce (sans doute stupide) Code:Que fait le compilateur Java avec plusieurs bornes génériques?

public <T extends Appendable & Closeable> void doStuff(T object) 
throws IOException{ 

    object.append("hey there"); 
    object.close(); 

} 

Je sais que le compilateur supprime les informations génériques, donc je suis intéressé par le code Java 1.4 équivalent à ce que le compilateur (je suis assez sûr le compilateur ne réorganise pas le code source, donc je demande une version équivalente source Java que les gens naïfs comme moi peut comprendre)

est-ce quelque chose comme ceci:

public void doStuff(Object object) 
throws IOException{ 

    ((Appendable)object).append("hey there"); 
    ((Closeable)object).close(); 

} 

Ou plutôt comme ceci:

public void doStuff(Object object) 
throws IOException{ 
    Appendable appendable = (Appendable) object; 
    Closeable closeable = (Closeable) object; 

    appendable.append("hey there"); 
    closeable.close(); 

} 

Ou encore comme ceci:

public void doStuff(Appendable appendable) 
throws IOException{ 
    Closeable closeable = (Closeable) appendable; 

    appendable.append("hey there"); 
    closeable.close(); 

} 

Ou encore une autre version?

+0

pourquoi ne pas décompiler le code avec javap pour savoir. Je soupçonne que ceci n'est pas défini et que les différents compilateurs pourraient le gérer différemment. –

+0

Je pourrais le faire, mais j'espérais de vraies réponses de gens intelligents qui m'expliqueraient pourquoi les choses sont ce qu'elles sont. –

Répondre

14

Signature de la méthode ressemble à public void doStuff(Appendable appendable), parce que

L'ordre des types dans une limite est seulement importante en ce que l'effacement d'une variable de type est déterminé par le premier type dans sa borne, et qu'une variable de type ou de type de classe ne peut apparaître que dans la première position .

(JLS §4.4 Type Variables)

Ce comportement peut être important si vous utilisez la réflexion pour accéder à cette méthode. Une autre utilisation de ce comportement consiste à conserver la compatibilité binaire avec les interfaces pré-génériques, comme décrit dans Generics Tutorial, section 10 (grâce à Mark Peters pour l'avoir signalé). C'est,

public static <T extends Object & Comparable<? super T>> T max(Collection<T> coll) 

est binaire compatible avec sa version pré-générique retour Object.


corps de la méthode est un équivalent de ce qui suit, mais je pense que ce sont des détails de mise en œuvre:

appendable.append("hey there"); 
((Closeable) appendable).close(); 
+3

+1, vous pouvez également consulter le tutoriel Generics, section 10 (http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf) qui examine le cas de Collections.max() '. 'max()' utilise les multiples limites '>' pour conserver la compatibilité binaire après avoir été mis à jour avec Generics. –

+0

@ Mark Peters ou vous devriez juste restaurer votre propre réponse. Qu'est ce qui ne va pas avec ça? –

+0

@seanizer: axtavt m'a battu pour dire la même chose, et le JLS est plus autoritaire qu'un tutoriel. J'ai trouvé deux réponses disant exactement la même chose mais avec des citations différentes n'était pas productif. @axtavt est libre d'inclure cela dans sa réponse s'il choisit. –

4

Je ne pouvais pas attendre, je devais y aller et répondre à ma propre question. La réponse est une combinaison de ma première et troisième versions: la première limite est utilisée comme type de variable, et l'objet est moulé à la seconde limite chaque fois que nécessaire. Ceci est le code d'octets résultant (j'ai ajouté une seule rupture de ligne pour une meilleure lisibilité):

// Method descriptor #20 (Ljava/lang/Appendable;)V 
    // Signature: <T::Ljava/lang/Appendable;:Ljava/io/Closeable;>(TT;)V 
    // Stack: 2, Locals: 2 
    public void doStuff(java.lang.Appendable object) throws java.io.IOException; 
    0 aload_1 [object] 
    1 ldc <String "hey there"> [26] 
    3 invokeinterface java.lang.Appendable.append(java.lang.CharSequence) : 
     java.lang.Appendable [28] [nargs: 2] 
    8 pop 
    9 aload_1 [object] 
    10 checkcast java.io.Closeable [34] 
    13 invokeinterface java.io.Closeable.close() : void [36] [nargs: 1] 
    18 return 
     Line numbers: 
     [pc: 0, line: 14] 
     [pc: 9, line: 15] 
     [pc: 18, line: 17] 
     Local variable table: 
     [pc: 0, pc: 19] local: this index: 0 type: rumba.dumba.Bumba 
     [pc: 0, pc: 19] local: object index: 1 type: java.lang.Appendable 
     Local variable type table: 
     [pc: 0, pc: 19] local: object index: 1 type: T 
+0

Cool! Mais puis-je vous suggérer d'utiliser java decompiler la prochaine fois pour la lisibilité? :) – AlexR

+0

Bonne idée, mais je suis paresseux, et j'ai juste dû ouvrir le fichier de classe en éclipse, alors je suis allé pour ce –

+1

rumba.dumba.Bumba – yegeniy

Questions connexes