如果您从 Scala 2.10.2 获取该类scala.runtime.AbstractPartialFunction
(我没有检查其他版本)并比较 的输出AbstractPartialFunction.class.getInterfaces()
,AbstractPartialFunction.class.getGenericInterfaces()
您可能会注意到,结果不匹配。通用接口是scala.Function1<T1, R>
和scala.PartialFunction<T1, R>
,而 getInterfaces() 仅返回scala.PartialFunction
。从scala文档中我可以看到通用信息是正确的,因为PartialFunction是一个Function1。
getInterfaces 的 javadoc 说:
如果此对象表示一个类,则返回值是一个数组,其中包含表示该类实现的所有接口的对象。数组中接口对象的顺序与该对象所表示的类的声明的implements 子句中接口名称的顺序相对应。
和 getGenericInterfaces 具有完全相同的文本。
由此(以及其他文本,包括 stackoverflow 信息)我得出结论,数组的顺序和长度是相等的。只是这里的情况并非如此。为什么?
到目前为止,我能够用几个 java7 和 java8 重现这个问题,没有尝试 java6 甚至 java5。
编辑:
AbstractPartialFunction 的 javap 输出(当然只有标头)是:
Compiled from "AbstractPartialFunction.scala"
public abstract class scala.runtime.AbstractPartialFunction<T1, R> implements scala.Function1<T1, R>, scala.PartialFunction<T1, R>`
Run Code Online (Sandbox Code Playgroud)
使用 asm lib 和 Textifier 在那里我可以看到这个头信息:
// class version 50.0 (50)
// access flags 0x421
// signature <T1:Ljava/lang/Object;R:Ljava/lang/Object;>Ljava/lang/Object;Lscala/Function1<TT1;TR;>;Lscala/PartialFunction<TT1;TR;>;
// declaration: scala/runtime/AbstractPartialFunction<T1, R> implements scala.Function1<T1, R>, scala.PartialFunction<T1, R>
public abstract class scala/runtime/AbstractPartialFunction implements scala/PartialFunction
Run Code Online (Sandbox Code Playgroud)
加上一个 ScalaSigAttribute。当然我没有展示这两种情况的方法
// Compiled from AbstractPartialFunction.scala (version 1.6 : 50.0, super bit)
// Signature: <T1:Ljava/lang/Object;R:Ljava/lang/Object;>Ljava/lang/Object;Lscala/Function1<TT1;TR;>;Lscala/PartialFunction<TT1;TR;>;
@scala.reflect.ScalaSignature(bytes="some bytes...")
public abstract class scala.runtime.AbstractPartialFunction implements scala.PartialFunction {
Run Code Online (Sandbox Code Playgroud)
类型的签名大致相当于以下 Java 声明:
class AbstractPartialFunction implements PartialFunction, Function1 {}
Run Code Online (Sandbox Code Playgroud)
PartialFunction扩展Function1:
// Compiled from PartialFunction.scala (version 1.6 : 50.0, no super bit)
// Signature: <A:Ljava/lang/Object;B:Ljava/lang/Object;>Ljava/lang/Object;Lscala/Function1<TA;TB;>;
@scala.reflect.ScalaSignature(bytes="some bytes...")
public abstract interface scala.PartialFunction extends scala.Function1 {
Run Code Online (Sandbox Code Playgroud)
以下是Java 类文件的结构:
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
}
Run Code Online (Sandbox Code Playgroud)
该类型实现的接口存储在常量池中,并通过接口数组中的引用记录:
类签名作为属性存储在属性数组中:
该
Signature
属性记录任何类、接口、构造函数或成员的通用签名信息,这些类、接口、构造函数或成员在 Java 编程语言中的通用签名将包括对类型变量或参数化类型的引用。
所以这是我对正在发生的事情的有根据的猜测:
Class.getInterfaces()
返回接口数组中的值Class.getGenericInterfaces()
使用类型签名构建其返回值此行为与 Oracle JDK 从等效 Java 源生成的字节码不同,但它显然通过了 JVM 在加载类时进行的所有检查。