Java 8接口默认方法似乎没有声明属性

在我的应用程序中,我遇到一个问题,当类中的getter仅在接口中默认(Java 8特性)时,结果没有Java Beans属性。 即普通方法调用它只是作为标准方法工作,但对于通过“属性”访问它突然表现不同……

这是一个测试用例:

import java.beans.Introspector; import java.util.Arrays; import java.util.stream.Collectors; import org.apache.commons.beanutils.PropertyUtils; public class test { public static void main (String[] arguments) throws Exception { // Normal language-level invocation, works fine. System.out.println (new Bean1 ().getFoo ()); System.out.println (new Bean2 ().getFoo ()); // Printing Java Beans properties; Bean2 doesn't have 'foo' property... System.out.println (Arrays.stream (Introspector.getBeanInfo (Bean1.class).getPropertyDescriptors ()) .map ((property) -> property.getName ()) .collect (Collectors.joining (", "))); System.out.println (Arrays.stream (Introspector.getBeanInfo (Bean2.class).getPropertyDescriptors ()) .map ((property) -> property.getName ()) .collect (Collectors.joining (", "))); // First call behaves as expected, second dies with exception. System.out.println (PropertyUtils.getProperty (new Bean1 (), "foo")); System.out.println (PropertyUtils.getProperty (new Bean2 (), "foo")); } public interface Foo { default String getFoo () { return "default foo"; } } public static class Bean1 implements Foo { @Override public String getFoo () { return "special foo"; } } public static class Bean2 implements Foo { } } 

结果:

 special foo default foo class, foo class special foo Exception in thread "main" java.lang.NoSuchMethodException: Unknown property 'foo' on class 'class test$Bean2' at org.apache.commons.beanutils.PropertyUtilsBean.getSimpleProperty(PropertyUtilsBean.java:1257) at org.apache.commons.beanutils.PropertyUtilsBean.getNestedProperty(PropertyUtilsBean.java:808) at org.apache.commons.beanutils.PropertyUtilsBean.getProperty(PropertyUtilsBean.java:884) at org.apache.commons.beanutils.PropertyUtils.getProperty(PropertyUtils.java:464) at test.main(test.java:21) 

问题:我做错了什么或者它是Java中的错误? 是否有一种解决方法,除了从不使用默认方法(对于getter / setter),以防您以后需要在某个时候访问它们作为“属性”?

我总是讨厌Java“按惯例的属性”,因为你打错了方式,所以会打破。

这似乎确实是Beans Introspector中的一个错误遗漏。 除了不使用default方法之外,还有一个解决方法:

 public static void main (String[] arguments) throws Exception { testBean(new Bean1()); System.out.println(); testBean(new Bean2()); } static void testBean(Object bean) throws Exception { PropertyDescriptor[] pd = Introspector.getBeanInfo(bean.getClass()).getPropertyDescriptors(); System.out.println(Arrays.stream(pd) .map(PropertyDescriptor::getName).collect(Collectors.joining(", "))); for(PropertyDescriptor p: pd) System.out.println(p.getDisplayName()+": "+p.getReadMethod().invoke(bean)); } public interface Foo { default String getFoo() { return "default foo"; } } public static class Bean1 implements Foo { @Override public String getFoo() { return "special foo"; } } public static class Bean2BeanInfo extends SimpleBeanInfo { private final BeanInfo ifBeanInfo; public Bean2BeanInfo() throws IntrospectionException { ifBeanInfo=Introspector.getBeanInfo(Foo.class); } @Override public BeanInfo[] getAdditionalBeanInfo() { return new BeanInfo[]{ifBeanInfo}; } } public static class Bean2 implements Foo { } 
 class, foo class: class helper.PropTest$Bean1 foo: special foo class, foo class: class helper.PropTest$Bean2 foo: default foo 

快速解决方法:

 try { return PropertyUtils.getProperty(bean, property); } catch (NoSuchMethodException e) { String getMethod = "get" + property.substring(0, 1).toUpperCase() + property.substring(1); return MethodUtils.invokeMethod(bean, getMethod, new Object[]{}); } 

我不知道我的答案是否有用,但我通过使用Spring的BeanUtils.getPropertyDescriptors(clazz)解决了类似的问题。 它了解默认方法。