簡體   English   中英

getDeclaredMethods() 在 Java 7 和 Java 8 中的行為不同

[英]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()返回的abstractdefault方法都有注釋,但只有abstract具有正確的非泛型參數。 所以在我看來,這個實現細節部分違背了通過注釋搜索方法的目的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM