2010-11-23 9 views
12

Tener un vistazo a esto (posiblemente estúpida) Código:¿Qué hace el compilador de Java con múltiples límites genéricos?

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

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

} 

Sé que el compilador elimina la información genérica, así que estoy interesado en Java 1.4 código equivalente a lo que hace el compilador (estoy bastante seguro el compilador no reorganizar el código fuente, por lo que estoy pidiendo una versión de código Java equivalente que los ingenuos como yo puede entender)

IS es algo como esto:

public void doStuff(Object object) 
throws IOException{ 

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

} 

O más bien como esto:

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

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

} 

ni aun como este:

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

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

} 

O otra versión?

+0

¿por qué no descompilar el código con javap de averiguarlo. Sospecho que esto no está definido y los diferentes compiladores podrían manejarlo de manera diferente. –

+0

Podría hacer eso, pero esperaba respuestas reales de personas inteligentes que me explicaran por qué las cosas son lo que son. –

Respuesta

14

firma del método se ve como public void doStuff(Appendable appendable), porque

El orden de los tipos de un salto es sólo es significativo en que el borrado de una variable de tipo está determinado por el primer tipo en su límite, y que un tipo de clase o variable de tipo solo puede aparecer en la primera posición .

(JLS §4.4 Type Variables)

Este comportamiento puede ser importante si se utiliza la reflexión para acceder a este método.

Otro uso de este comportamiento es mantener la compatibilidad binaria con las interfaces pre genéricas, como se describe en Generics Tutorial, sección 10 (gracias a Mark Peters por señalarlo). Es decir,

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

es compatible a nivel binario con su versión pre-genérica regresar Object.


cuerpo del método es un equivalente de los siguientes, pero yo creo que es detalles de implementación:

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

+1, también puede consultar el Tutorial de Generics, sección 10 (http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf) que examina el caso de 'Collections.max() '. 'max()' utiliza los límites múltiples '>' para conservar la compatibilidad binaria después de ser adaptado con Generics. –

+0

@Mark Peters o simplemente debe recuperar su propia respuesta. ¿Qué pasa con eso? –

+0

@seanizer: axtavt me ganó para decir lo mismo, y el JLS tiene más autoridad que un tutorial. Pensé que dos respuestas que decían exactamente lo mismo pero con citas diferentes no eran productivas. @axtavt es libre de incluir eso en su respuesta si elige. –

4

No podía esperar, tenía que ir y responder mi propia pregunta. La respuesta es una combinación de mi primera y tercera versión: el primer límite se utiliza como tipo de variable y el objeto se convierte en el segundo límite siempre que sea necesario. Este es el código de bytes resultante (añadí un solo salto de línea para facilitar la lectura):

// 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

¡Genial! Pero, ¿puedo sugerirle que use el descompilador de Java la próxima vez para poder leerlo? :) – AlexR

+0

Buena idea, pero soy flojo, y solo tuve que abrir el archivo de clase en eclipse, así que fui por ese –

+1

rumba.dumba.Bumba – yegeniy

Cuestiones relacionadas