簡體   English   中英

Java 8和Bean Info Introspector中的接口中的默認方法

[英]Default method in interface in Java 8 and Bean Info Introspector

我對Interface和BeanInfo Introspector中的默認方法有一點問題。 在此示例中,有接口:接口

public static interface Interface {
    default public String getLetter() {
        return "A";
    }
}

以及兩個類ClassA和ClassB:

public static class ClassA implements Interface {
}

public static class ClassB implements Interface {
    public String getLetter() {
        return "B";
    }
}

在主要方法中,app從BeanInfo打印PropertyDescriptors:

public static String formatData(PropertyDescriptor[] pds) {
    return Arrays.asList(pds).stream()
            .map((pd) -> pd.getName()).collect(Collectors.joining(", "));

}

public static void main(String[] args) {


    try {
        System.out.println(
                formatData(Introspector.getBeanInfo(ClassA.class)
                        .getPropertyDescriptors()));
        System.out.println(
                formatData(Introspector.getBeanInfo(ClassB.class)
                        .getPropertyDescriptors()));
    } catch (IntrospectionException e) {
        e.printStackTrace();
    }

}

結果是:

class
class, letter

為什么默認方法“字母”在ClassA中不顯示為屬性? 它是錯誤還是功能?

我猜想,即使使用Java 8虛擬擴展方法(又稱防御者,默認方法), Introspector也不處理interface層次結構鏈,但接口可能有點類似於屬性方法。 這是一個聲稱很簡單的內省器: BeanIntrospector

無論是否可以認為這是一個錯誤,這都是灰色區域,這就是我這么認為的原因。

顯然,現在,一個類可以從接口“繼承”一種方法,該方法具有通常被認為是getter / setter / mutator的所有特性。 但是與此同時,這整個過程都違背了接口的目的-接口不可能提供任何可以視為屬性的東西,因為它是無狀態且無行為的,僅用於描述行為。 除非防御者方法訪問了具體實現的真實屬性,否則它們基本上都是靜態的。

另一方面,如果我們假設防御者是正式繼承的 (相對於提供默認實現 (定義不清楚)),它們將導致在實現類中創建綜合方法,並且這些綜合方法屬於該類並被遍歷作為PropertyDescriptor查找的一部分。 顯然這不是事實,否則整個事情都會奏效。 :)似乎防御者的方法在這里得到了某種特殊待遇。

我也認為這是一個錯誤。 您可以為您的類使用專用的BeanInfo並通過提供類似的東西來解決此問題:

/* (non-Javadoc)
 * @see java.beans.SimpleBeanInfo#getAdditionalBeanInfo()
 */
@Override
public BeanInfo[] getAdditionalBeanInfo()
{
    Class<?> superclass = Interface.class;
    BeanInfo info = null;

    try
    {
        info = Introspector.getBeanInfo(superclass);
    }
    catch (IntrospectionException e)
    {
        //nothing to do
    }

    if (info != null)
        return new BeanInfo[] { info };

    return null;
}

這是因為您只在Interface和ClassB上擁有方法,而沒有直接在ClassA上擁有方法。 但是,對我來說,這聽起來像個錯誤,因為我希望該屬性出現在列表中。 我懷疑Inrospector尚未趕上Java 8功能。

調試顯示此方法已在Introspector#getPublicDeclaredMethods()處過濾掉:

if (!method.getDeclaringClass().equals(clz)) {
    result[i] = null; // ignore methods declared elsewhere
}

其中clz是所討論類的完全限定名稱。

由於ClassB具有此方法的自定義實現,因此它成功通過了檢查,而ClassA沒有。

暫無
暫無

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

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