2010-07-14 73 views
12

使用Asm定义简单的getter和setter很容易(幸运的是甚至可以在其常见问题中解释它)。但是有一件事没有提到,而且我一直无法找到文档,那就是如何使用泛型类型信息来实现这些。使用Asm字节码生成器(ClassWriter)生成具有泛型类型的方法

我实际上能够很容易地确定泛型类型信息(因为代码将采用现有的字段和/或方法,并且存在完整的泛型类型处理和分辨率)。我只需要为包含泛型类型的类型生成泛型版本。我希望这与修改Asm ClassWriter/MethodVisitor调用的签名一样简单,但文档中的某些注释表明它可能并不那么容易(因为泛型信息存储在与常规信息不同的地方)。看起来入口点是“ClassWriter.visitField/Method(....,String signature) - 注意它是包含正常的非泛型类信息的”描述“,但是术语”签名“ (在JLS中)专指泛型 - 包括类型信息

回答

8

您可以使用ASM的SignatureWriter类构建签名

例如,假设你希望写的签名这个方法:

public <K> void doSomething(K thing) 

您可以使用此代码:

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(); 

即相当于:

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

这很有用,谢谢。我现在的具体问题似乎是结果签名不能正确写入类文件,尽管我使用了正确的格式(据我所知)。 但是,也许我应该仔细检查SignatureWriter以确保... – StaxMan 2010-07-29 22:03:16

+1

@StaxMan:我也遇到了麻烦。也许这篇文章将有助于:[Classworking toolkit:泛型与ASM](http://www.ibm.com/developerworks/java/library/j-cwt02076.html) – 2010-07-29 22:07:57

+0

啊!我终于在代码中发现了真正的问题:我在ClassVisitor.visit()中有参数V1_2;对于要支持的泛型(和注释),这需要V1_5或更高版本。谢谢你的帮助! – StaxMan 2010-07-30 06:25:57

-1

根据我的经验,大多数即时字节码生成库对泛型没有很好的支持;但是已擦除的类可以正常工作(除非您想要当然,以后反思这些类)

+1

不幸的是我特别需要自省 - 这就是使用库将实际构建串行器和反序列化器的方式。 : -/ 是的,代码清除可以正常工作......我可能不得不寻找另一种方法来使事情发挥作用,或许通过添加新种类的注释来有效地复制签名。 – StaxMan 2010-07-28 02:03:23