2010-07-14 28 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

相關問題