2014-03-07 59 views
4

如果您從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。Class#getInterfaces()和Class#getGenericInterfaces()返回不同長度的數組

爲getInterfaces的Javadoc說:

如果該對象表示一個類,返回值是包含表示由類實現的所有接口的對象的數組。數組中接口對象的順序對應於由此對象表示的類的聲明的implements子句中的接口名稱的順序。

和getGenericInterfaces具有完全相同的文本。

從那裏(和其他文本,包括stackoverflow信息)我會得出結論,秩序和數組的長度是相等的。只有這不是這種情況。爲什麼?

到目前爲止,我能夠重現這與幾個java7和java8,沒有嘗試java6甚至java5。

編輯:

的javap的輸出爲AbstractPartialFunction(僅當然的報頭)爲:

Compiled from "AbstractPartialFunction.scala" 
public abstract class scala.runtime.AbstractPartialFunction<T1, R> implements scala.Function1<T1, R>, scala.PartialFunction<T1, R>` 

使用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 

加上一個ScalaSigAttribute。當然,我並沒有表現出在這兩種情況下

+0

神奇的「通用」字呢? – Antoniossss

+0

我知道一個有泛型信息,另一個沒有。這不是問題 – blackdrag

+0

當你用javap檢查類型時,你會看到什麼? – McDowell

回答

3
// 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 { 

類型的簽名大致相當於這個Java聲明的方法:

class AbstractPartialFunction implements PartialFunction, Function1 {} 

PartialFunction延伸功能1

// 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 { 

這是the structure of a Java class file

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]; 
} 

類型工具被存儲在常量池中並記錄通過引用在接口的接口陣列:

class signature is stored as an attribute屬性陣列:

Signature屬性記錄Java編程語言中通用簽名將包含對類型變量的引用的任何類,接口,構造函數或成員的通用簽名信息s或參數化類型。

因此,這裏是我對所發生的事情的猜測:

  • Class.getInterfaces()接口返回值陣列
  • Class.getGenericInterfaces()使用類型簽名
  • 斯卡拉編譯器生成它的返回值刪除功能1接口數組,因爲PartialFunction延伸功能1
  • Scala編譯器保留類型的簽名,是

此行爲是到了Oracle JDK從相當於Java源代碼生成的字節碼不同,但是這顯然通過所有的檢查JVM在加載類時產生。

+0

我幾乎可以接受答案,但Javadoc說這個類實現的** all **接口出現在數組中。這裏不是這種情況。或者我可以在這裏從字面上理解javdoc?它提到了執行條款的額外內容。接下來的事情是...爲什麼Function1是通用簽名?還有兩件事......僅僅是因爲代碼通過了Verifier,並不意味着它是有效的字節碼,而是按照JVM人的意圖生成的。另外,我不認爲scala.reflect.ScalaSignature對於Java和這兩種方法來說都非常重要。 – blackdrag

0

所以完全回答我的問題。我還是會接受對方雖然...

返回數組的長度不同,因爲仿製藥的簽名,並在字節碼的正常簽名不匹配。我懷疑這樣做是合法的,但由於它似乎沒有被檢查,所以沒有人抱怨。像這樣的答案:Proper way to get a generics type argument雖然會爲來自javac生成的世界之外的案例留下錯誤的印象。

此外,全部接口意味着不是所有的層次結構,只有直接實施的接口。在Java中,將會在implements子句中找到什麼。 Class的android版本的javadoc使用了不同的措辭,這是一個很好的理由。無論如何,正如已經說過的那樣,它可能會有所不同 - 特別是如果該類不是來自javac。