整理Classworking工具箱泛型与ASMWord文档下载推荐.docx
- 文档编号:17366173
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:16
- 大小:29.62KB
整理Classworking工具箱泛型与ASMWord文档下载推荐.docx
《整理Classworking工具箱泛型与ASMWord文档下载推荐.docx》由会员分享,可在线阅读,更多相关《整理Classworking工具箱泛型与ASMWord文档下载推荐.docx(16页珍藏版)》请在冰豆网上搜索。
当您在Java源代码中引用类名称时,您或许会也或许不会真正将包限定作为名称的一部分。
您总是可以包含包限定(形如java.lang.String),但您也可以为了省事而忽略它——如果类来自java.lang包或已import到源文件中。
这种包含包限定的类名称结构就称为“完全限定”类名。
在实际的二进制类内部,类名称总是在一个包中指定的。
但这种名称的格式与Java源代码中的完全限定类名略有差别,使用正斜杠(“/”)取代圆点(“.”)。
例如,在String类中,名称的内部形式为java/lang/String。
如果您尝试将一个类文件作为文本输出或查看,那么通常会看到上述形式的多个字符串,每个字符串都是对某个类的引用。
采用这种内部形式的类引用是作为字段和方法描述符的一部分使用的。
字段描述符指定类中定义的一个类的准确类型。
所使用的表示法取决于字段是简单对象类型、简单原语类型还是数组类型。
简单对象类型的表示法为,以‘L’开头,后接对象类名称的内部形式,以‘;
’结尾。
原语类型的表示法为,各类型使用一个单独的字母(如‘I’表示int、‘Z’表示布尔型)。
数组类型的表示法为,以‘[’作为数组项类型(其本身也可为数组类型)的前缀修饰符。
表1给出了关于各字段描述符的示例,另外还列出了相应的Java源代码声明:
表1.字段描述符示例
描述符
源代码
Ljava/lang/String;
String
I
int
[Ljava/lang/Object;
Object[]
[Z
boolean[]
[[Lcom/sosnoski/generics/FileInfo;
com.sosnoski.generics.FileInfo[][]
方法描述符结合了字段描述符,以指定方法的参数类型和返回类型。
方法描述符的格式非常易于理解。
以‘(’开始,后接参数的字段描述符(均一起运行),随后是‘)’,最后以返回类型结尾(若返回类型为void,则以‘V’结尾)。
表2给出了方法描述符的一些示例,同时还列出了相应的Java源代码声明(注意方法名称和参数名称本身并非方法描述符的一部分,所以在表中使用了占位符):
表2.方法描述符示例
(Ljava/lang/String;
)I
intmmm(Stringx)
(ILjava/lang/String;
)V
voidmmm(intx,Stringy)
(I)Ljava/lang/String;
Stringmmm(intx)
)[C
char[]mmm(Stringx)
voidmmm(intx,Stringy,FileInfo[][]z)
在虚线处签名
上面已经介绍了字段和方法描述符,那么接下来将介绍签名。
签名格式扩展了字段和方法描述符的概念,将泛型类型信息包含于其中。
不幸的是,泛型的复杂性(包括可能出现的各种上下界变化等)意味着签名无法像描述符那样简单地说明。
签名的语法(详见JVMspecificationchangesforJava1.5的第4章)包含21个独立产品项。
本文无法全面涉及,这里将给出几个示例,下一节将针对这部分示例展开讲解。
清单1是上一期文章中所用的一个数据结构类的部分源代码,以及相应的签名字符串。
在本例中,类本身并非参数化类型,但字段和方法使用了参数化的java.util.List:
清单1.简单的签名示例
publicclassDirInfo
{
privatefinalList<
FileInfo>
m_files;
DirInfo>
m_directories;
...
publicList<
getDirectories(){
returnm_directories;
}
getFiles(){
returnm_files;
...
}
Classsignature:
{none}
m_filessignature:
Ljava/util/List<
Lcom/sosnoski/generics/FileInfo;
>
;
m_directoriessignature:
Lcom/sosnoski/generics/DirInfo;
getDirectories()signature:
()Ljava/util/List<
getFiles()signature:
由于类并非参数化类型,所以未为该类本身的二进制类表示添加任何签名。
但确实为使用参数化类型的字段和方法使用了签名。
m_files字段签名表示这是一个List,且类型为FileInfo;
而m_directories字段签名则表示这是一个类型为DirInfo的List。
同样,getDirectories()方法签名表示该方法返回一个类型为DirInfo的List,而getFiles()签名则表示该方法返回一个类型为FileInfo的List。
迄今为止,一切看起来都相当容易理解,但事实真是如此吗?
下面让我们看看清单2,其中给出了一个简单的参数化类定义和相应的签名字符串:
清单2.参数化类签名示例
publicclassPairCollection<
T,U>
implementsIterable<
T>
/**Collectionwithfirstcomponentvalues.*/
privatefinalArrayList<
m_tValues;
/**Collectionwithsecondcomponentvalues.*/
U>
m_uValues;
publicvoidadd(Tt,Uu){
m_tValues.add(t);
m_uValues.add(u);
publicUget(Tt){
intindex=m_tValues.indexOf(t);
if(index>
=0){
returnm_uValues.get(index);
}else{
returnnull;
<
T:
Ljava/lang/Object;
U:
Ljava/lang/Iterable<
TT;
m_tValuessignature:
Ljava/util/ArrayList<
m_uValuessignature:
TU;
addsignature:
(TT;
getsignature:
)TU;
由于清单2中的类为参数化类型,所以类签名需要以二进制类形式表示。
与源代码相比,签名的文本要长一些,但如果您了解到,源代码中省略的类型参数的所有可选组件都包含在签名中,那么理解起来也就不太困难了。
签名的第一部分(位于尖括号‘<
...>
’内)就是该类的类型参数定义清单。
这些定义的形式都相同,类型参数名称后接类型的类边界和接口边界(若存在)的字段描述符。
各字段描述符前加‘:
’字符。
由于清单2源代码未为类的类型参数指定任何边界,因此其边界均为默认的类边界java.lang.Object。
类签名的第二部分(尖括号外)给出了超类和超接口(若存在)的签名。
在清单2所示的例子中,未指定任何超类,因此签名以java.lang.Object作为超类。
这里指定了超接口,为Iterable<
。
在签名中可以看到预期结果,源代码中使用的只是‘<
’,而签名中使用的是‘<
’。
原因在于签名需要区分类名称和类型变量名称,第一个‘T’标识紧随其后的内容为类型变量名,而结尾的‘;
’表示名称结束。
清单2中的字段和方法签名利用了与超接口签名相同的变量格式类型,其他都与前面介绍的内容相同。
回页首
ASM中的泛型
本系列的前几期文章中已介绍过(链接参见参考资料部分),ASM使用了一种访问器(visitor)模式来处理二进制类表示。
这种访问器模式是双向的:
您可以解析一个现有类,得到类组件的处理程序访问器方法的调用序列,也可以实现对类写入器的访问器方法的同类调用序列,以生成一个二进制类表示。
这一解析器/写入器对称使ASM在您仅修改类的特定方面的情况下尤为方便——您可将类写入器作为类解析器事件的处理程序的基础,仅重写基写入器来处理您想更改的事件。
解析器(或读取器)和写入器都是非常有用的独立组件。
ASM2.X全面支持Java5JVM更改,包括读取和写入签名。
签名的基本处理是通过直接传递给恰当的访问器方法的值自动实现的。
另外,ASM2.X还增加了对签名字符串(有时非常复杂)编码进行解析的支持,从而可翻译签名细节。
按照ASM的基本原理,相同的接口还可供写入器使用以按需生成签名字符串。
在这一节中,我将介绍ASM如何将基本签名作为textblob处理,又是如何详细解析基本签名的。
所有部分的签名
ASM中将签名作为textblob处理,这一方式直接内建于基本类、字段和方法的访问器调用中。
清单3展示了org.objectweb.asm.ClassVisitor接口中的相应方法:
清单3.类、字段和方法的访问器方法
publicinterfaceClassVisitor
voidvisit(intversion,intaccess,Stringname,Stringsignature,
StringsuperName,String[]interfaces);
FieldVisitorvisitField(intaccess,Stringname,Stringdesc,
Stringsignature,Objectvalue);
MethodVisitorvisitMethod(intaccess,Stringname,Stringdesc,
Stringsignature,String[]exceptions);
清单中的各访问器方法将签名字符串作为参数。
若相应的类、字段或方法非泛型,则在调用方法时将返回null值。
清单4显示了签名相关方法的实际应用。
其中用mons.EmptyVisitor类作为基础实现了一个访问器类,这样我只需重写想使用的方法即可。
所提供的方法实现仅输出整体签名信息、本清单所示类中各字段和方法的描述符和签名信息。
清单4的末尾处展示了在清单1所示的完整DirInfo类中使用此访问器时所生成的输出:
清单4.签名相关方法的实际应用
publicclassShowSignaturesVisitorextendsEmptyVisitor
publicvoidvisit(intversion,intaccess,Stringname,Stringsig,
Stringsname,String[]inames){
System.out.println("
Class"
+name+"
signature:
"
);
"
+sig);
super.visit(version,access,name,sig,sname,inames);
publicFieldVisitorvisitField(intaccess,Stringname,Stringdesc,
Stringsig,Objectvalue){
Field"
descriptorandsignature:
+desc);
returnsuper.visitField(access,name,desc,sig,value);
publicMethodVisitorvisitMethod(intaccess,Stringname,Stringdesc,
Stringsig,String[]exceptions){
Method"
()descriptorandsignature:
returnsuper.visitMethod(access,name,desc,sig,exceptions);
Classcom/sosnoski/generics/DirInfosignature:
null
Fieldm_filesdescriptorandsignature:
Ljava/util/List;
Fieldm_directoriesdescriptorandsignature:
Fieldm_lastModifydescriptorandsignature:
Ljava/util/Date;
Method<
init>
(Ljava/io/File;
MethodgetDirectories()descriptorandsignature:
()Ljava/util/List;
MethodgetFiles()descriptorandsignature:
MethodgetLastModify()descriptorandsignature:
()Ljava/util/Date;
签名分析
除将签名作为字符串处理外,ASM还支持在细节级处理签名。
org.objectweb.asm.signature.SignatureReader类解析一个签名字符串,并生成对org.objectweb.asm.signature.SignatureVisitor接口的调用序列。
org.objectweb.asm.signature.SignatureWriter类实现访问器接口,并从访问器方法调用序列中构建出签名字符串。
很不幸,细节级接口有些复杂,但其原因在于签名定义的复杂性,而不是ASM代码处理不力。
SignatureVisitor接口展现了这一复杂性,它定义了16个可在签名处理过程中包含的独立方法调用。
当然,绝大多数签名仅使用这些方法中的一小部分。
为举例说明ASM的细节级签名处理,我将解析本文前面所讨论的某些签名,从而介绍方法。
为此,我编写了TraceSignatureVisitor类,清单5展示了该类的部分代码,该清单中的AnalyzeSignaturesVisitor用于驱动签名处理。
当AnalyzeSignaturesVisitor用做类的访问器时,它会为所发现的各签名创建一个SignatureReader,将TraceSignatureVisitor类的一个实例作为签名组件访问器调用的目标传递。
用于解析签名的SignatureReader调用取决于签名的形式:
对于类和方法签名,恰当的方法是accept();
对于字段签名,应使用acceptType()调用。
清单5.签名分析
publicclassTraceSignatureVisitorimplementsSignatureVisitor
publicvoidvisitFormalTypeParameter(Stringname){
visitFormalTypeParameter("
)"
publicSignatureVisitorvisitClassBound(){
visitClassBound()"
returnthis;
publicSignatureVisitorvisitInterfaceBound(){
visitInterfaceBound()"
publicSignatureVisitorvisitSuperclass(){
visitSuperclass()"
publicSignatureVisitorvisitInterface(){
visitInterface()"
publicSignatureVisitorvisitParameterType(){
visitParameterType()"
publicclassAnalyzeSignaturesVisitorextendsEmptyVisitor
if(sig!
=null){
newSignatureReader(sig).accept(newTraceSignatureVisitor());
newSignatureReader(sig).acceptType(newTraceSignatureVisitor());
r
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 整理 Classworking 工具箱 ASM