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

标签 java java-8 javabeans default-method

在我的应用程序中,我遇到了一个问题,即当类中的 getter 仅在接口(interface)中默认设置时(Java 8 功能),结果没有 Java Beans 属性。 IE。对于普通方法调用,它就像标准方法一样工作,但对于通过“属性”访问,它突然表现不同......

这是一个测试用例:

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

关于Java 8 接口(interface)默认方法似乎没有声明属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31703563/

相关文章:

java - 如何使用 Apache HttpClient 发布 JSON 请求?

java - Hibernate:org.hibernate.AssertionFailure:com.xxx.Bean 条目中的 id 为空

java - 如何更改游戏框架名称?

java - 如何在 Javabean 中将属性标记为 transient 以避免被 XMLEncoder 序列化?

java - 创建了java计算器,我想使用答案并替换为第一个数字?

java - 如何让 MigLayout 4.2 与 JavaFX 8 协同工作?

java - 以下代码是否应该在 Java 1.8 下编译

java-8 - Lombok @Builder.Default 强制默认可选值为 null

mongodb - 将 Java bean 和 Scala 案例类映射到 MongoDB 对象

java - spring 外部属性文件;文件未找到异常