我目前正在玩ASM并分析类的泛型签名。本节中记录的可能内容描述为here,可以使用以下语法进行总结:
TypeSignature: Z | C | B | S |我| F | J | D | FieldTypeSignature
FieldTypeSignature: ClassTypeSignature | [TypeSignature | TypeVar
ClassTypeSignature: L Id(/ Id) TypeArgs? (.Id TypeArgs?)*; *
TypeArgs: < TypeArg +>
TypeArg: ** | (+ | - )? FieldTypeSignature *
TypeVar: T Id;
然而,我发现一个案例并非如此:
trait SomeTrait
class SomeClass[T <: SomeTrait]
SomeClass
的通用签名:<T::LSomeTrait;>Ljava/lang/Object;
我不明白为什么::
出现在这里,这是什么意思。从语法的角度来看,Doubled :
无效。有趣的是,如果我将trait
替换为abstract class
,则::
将被替换为单个:
(预期的内容)。
有什么想法吗?
答案 0 :(得分:3)
类文件规范说明(在4.7.9.1. Signatures部分中):
ReferenceTypeSignature:
ClassTypeSignature
TypeVariableSignature
ArrayTypeSignature
TypeParameters:
< TypeParameter {TypeParameter} >
TypeParameter:
Identifier ClassBound {InterfaceBound}
ClassBound:
: [ReferenceTypeSignature]
InterfaceBound:
: ReferenceTypeSignature
将此应用于<T::LSomeTrait;>
表示:
TypeParameters
=> < TypeParameter {TypeParameter} >
=> < Identifier ClassBound {InterfaceBound} {TypeParameter} >
=> < T ClassBound {InterfaceBound} {TypeParameter} >
=> < T : [ReferenceTypeSignature] {InterfaceBound} {TypeParameter} >
=> < T : {InterfaceBound} {TypeParameter} >
=> < T : : ReferenceTypeSignature {TypeParameter} >
=> < T : : LSomeTrait; {TypeParameter} >
=> < T : : LSomeTrait; >
=> <T::LSomeTrait;>
总而言之,第一个冒号引入了类绑定,第二个冒号引入了接口绑定。两个冒号保持在一起这一事实意味着没有阶级约束。
使用类和接口签名:
scala> trait T
defined trait T
scala> abstract class A
defined class A
scala> class C[X <: A with T]
defined class C
scala> :javap C
Size 554 bytes
MD5 checksum 6273d85df5987e350e7112726756a55f
Compiled from "<console>"
public class C<X extends A & T> extends java.lang.Object
minor version: 0
major version: 50
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Utf8 C
#2 = Class #1 // C
#3 = Utf8 <X:LA;:LT;>Ljava/lang/Object;
...