[英]getDeclaredMethods() behaving differently in Java 7 vs. Java 8
考慮以下小例子:
package prv.rli.codetest;
import java.lang.reflect.Method;
public class BreakingInterfaces {
interface Base {
BaseFoo foo();
interface BaseFoo {
}
}
interface Derived extends Base {
DerivedFoo foo();
interface DerivedFoo extends BaseFoo {
}
}
public static void main(String[] args) {
dumpDeclaredMethods(Derived.class);
}
private static void dumpDeclaredMethods(Class<?> class1) {
System.out.println("---" + class1.getSimpleName() + "---");
Method[] methods = class1.getDeclaredMethods();
for (Method method : methods) {
System.out.println(method);
}
System.out.println("----------");
}
}
如果你用 jdk1.7.0.55 編譯上面的例子,輸出是:
---Derived---
public abstract BreakingInterfaces$Derived$DerivedFoo BreakingInterfaces$Derived.foo()
----------
但是當使用 jdk1.8.0.25 時,輸出是:
---Derived---
public abstract prv.rli.codetest.BreakingInterfaces$Derived$DerivedFoo prv.rli.codetest.BreakingInterfaces$Derived.foo()
public default prv.rli.codetest.BreakingInterfaces$Base$BaseFoo prv.rli.codetest.BreakingInterfaces$Derived.foo()
----------
有誰知道,這是否是 jdk1.8.0.25 中的一個錯誤,或者為什么公共默認方法在這里重新出現?
getDeclaredMethods()
在這里的行為是正確的,因為它會准確地告訴您它在類中找到了什么。 如果您輸入使用 Java 7 目標(或較舊的編譯器)編譯的interface
,您將看到與getDeclaredMethods()
的 Java 7 實現的輸出沒有區別。
這是編譯器的行為不同。 在 Java 8 中編譯這樣的子interface
時,將生成橋接方法,該方法不會為 Java 7 目標生成,因為它甚至不可能用於 Java 7 目標。
現在為接口生成橋接方法的原因是您通常擁有比接口更多的實現類,因此在接口中使用default
橋接方法可以避免將橋接方法添加到每個實現中。 此外,如果只有一個abstract
方法而沒有要實現的橋接方法,它會使 lambda 類的生成變得更加容易。
當interface
層次結構需要橋接方法但不提供default
,編譯器必須使用LambdaMetafactory.altMetafactory
而不是LambdaMetafactory.metafactory
生成代碼,指定所需的每個橋接方法。
恕我直言,但它必須在平行宇宙中,Javadoc 的措辭充分解釋了這種行為: https ://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getDeclaredMethods-- . “所有聲明的方法”的數組結果是“用戶聲明的所有方法以及 StackOverflow 上解釋的一些底層實現細節”的數組。 更糟糕的是,我發現注釋有些奇怪:我在應用注釋時覆蓋了泛型方法, getDeclaredMethods()
返回的abstract
和default
方法都有注釋,但只有abstract
具有正確的非泛型參數。 所以在我看來,這個實現細節部分違背了通過注釋搜索方法的目的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.