2010-07-14 8 views
12

Definir getters y setters simples es fácil usando Asm (y afortunadamente incluso se explica en sus preguntas frecuentes). Pero una cosa que no se menciona, y para la cual no he podido encontrar la documentación, es cómo implementar estos usando información de tipo genérico.Generar métodos con tipos genéricos con generador de códigos de bytes Asm (ClassWriter)

De hecho, soy capaz de determinar la información de tipo genérico con bastante facilidad (dado que el código tomará los campos y/o métodos existentes y existe una resolución y manejo completo del tipo genérico). Solo necesito generar una versión genérica para los tipos que tienen el tipo genérico incluido.

Espero que esto sea algo tan fácil como modificar la firma Asm Las llamadas ClassWriter/MethodVisitor toman, pero algunos comentarios en la documentación indican que podría no ser tan fácil (ya que la información genérica se almacena en un lugar diferente que la información normal).

EDITAR: se parece a punto de entrada es "ClassWriter.visitField/Método (...., cadena de firma) - en cuenta que se trata de 'descripción' que contiene información de la clase no genérica normal, pero término 'firma' (en JLS) se refiere específicamente a los genéricos, incluida la información de tipo

Respuesta

8

Puede construir la firma usando la clase SignatureWriter de ASM.

Por ejemplo, supongamos que desea escribir la firma para este método:

public <K> void doSomething(K thing) 

Usted podría utilizar este código:

SignatureWriter signature = new SignatureWriter(); 
signature.visitFormalTypeParameter("K"); 

// Ensure that <K> extends java.lang.Object 
{ 
    SignatureVisitor classBound = signature.visitClassBound(); 
    classBound.visitClassType(Type.getInternalName(Object.class)); 
    classBound.visitEnd(); 
} 

// The parameter uses the <K> type variable 
signature.visitParameterType().visitTypeVariable("K"); 

// The return type uses the void primitive ('V') 
signature.visitReturnType().visitBaseType('V'); 

signature.visitEnd(); 

String signatureString = signature.toString(); 

que es equivalente a:

String signatureString = "<K:Ljava/lang/Object;>(TK;)V;" 
+0

Esto es útil, gracias. Mi problema específico en este momento parece ser que la firma resultante de alguna manera no está escrita correctamente en el archivo de clase, aunque utilizo el formato correcto (hasta donde yo sé). Pero tal vez debería volver a verificar con SignatureWriter para asegurarme ... – StaxMan

+1

@StaxMan: También he tenido problemas para compartirlo. Tal vez este artículo ayude: [Kit de herramientas para la clase: genéricos con ASM] (http://www.ibm.com/developerworks/java/library/j-cwt02076.html) –

+0

¡Ah! FINALMENTE encontré el problema real en mi código: tenía el argumento V1_2 en ClassVisitor.visit(); y esto necesita ser V1_5 o superior para genéricos (y anotaciones) a ser compatibles. ¡Gracias por tu ayuda! – StaxMan

-1

En mi experiencia, la mayoría de las librerías de generación de códigos de byte no son compatibles con los tipos genéricos, pero las clases borradas funcionan bien (a menos que desee introspect esas clases más adelante, por supuesto).

+1

Por desgracia, específicamente, se necesita introspección, así es como usar la biblioteca realmente construirá serializadores y deserializadores. : -/ Sí, el borrado cifrado funcionaría bien ... y podría tener que encontrar otra manera de hacer que las cosas funcionen, tal vez agregando nuevos tipos de anotaciones para replicar firmas de forma efectiva. – StaxMan

Cuestiones relacionadas