[英]Introspector getBeanInfo on bean with generic implemented method
[英]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.