【问题标题】:why default method not recognized as property(getter/setter)?为什么默认方法不被识别为属性(getter/setter)?
【发布时间】:2019-04-02 04:09:09
【问题描述】:

界面:

public interface SomeInt{
   Integer getX();
   void setX(Integer value);
   default Integer getY(){
      return getX();
   }
   default void setY(Integer value){
       setX(value);
   }
}

一个类实现它:

public class A implements SomeInt{
  private Integer x;
  public Integer getX(){
     return x;
  }
  public void setX(Integer value){
     x = value;
  }
}

初始化后,我可以调用getY & setY方法,得到正确的返回值。 但是我不能在 JSP(EL) 中使用它,比如${instance_of_class_a.y}。并且属性 Y 不在 IDEA 的变量列表中(调试模式)。

如果我在 A 类中显式添加 getY 和 setY,一切正常。 为什么?我认为默认方法就像一个编译器糖。

对不起,我的英语很差,代码中的错误,我已经更正了。

【问题讨论】:

  • 因为你的班级没有任何名为y的属性
  • 您的代码错误。您如何在返回StringgetY() 中返回Integer (getX())?此外,接口中的setX() 没有参数,但您的覆盖有参数。这段代码甚至无法编译。
  • 我已经编辑了代码。我确定原始源代码(有点复杂)已成功编译。而且我可以在 EL 中获取属性 X(或除 Y 之外的任何其他属性,该属性未在 classA 中显式声明(仅在 someInt 中定义为默认值)。

标签: java pojo default-method


【解决方案1】:

这里的问题写得有点糟糕,所以可能出了点问题。 尤其是错别字加@Override

interface SomeInt {
    int getX();

    void setX(int x);

    default int getY() {
        return getX();
    }

    default void setY(int value) {
        setX(value);
    }
}

static class A implements SomeInt {
    private int x;

    @Override
    public int getX() {
        return x;
    }

    @Override
    public void setX(int value) {
        x = value;
    }
}

    System.out.println("Methods:");
    for (Method m : A.class.getMethods()) {
        System.out.printf("+ %s%n", m.getName());
    }
    for (Method m : A.class.getDeclaredMethods()) {
        System.out.printf("- %s%n", m.getName());
    }

一般对于 getter/setter 使用 Class.getMethods

Methods:
+ setX
+ getX
...
+ setY
+ getY
- setX
- getX

【讨论】:

    【解决方案2】:

    我想我已经找到答案了。

    BeanELResover 使用 java.beans.Introspector 来获取 BeanInfo(Properties)

    public static BeanInfo getBeanInfo(Class<?> beanClass)
            throws IntrospectionException
        {
            if (!ReflectUtil.isPackageAccessible(beanClass)) {
                return (new Introspector(beanClass, null, USE_ALL_BEANINFO)).getBeanInfo();
            }
            ThreadGroupContext context = ThreadGroupContext.getContext();
            BeanInfo beanInfo;
            synchronized (declaredMethodCache) {
                beanInfo = context.getBeanInfo(beanClass);
            }
            if (beanInfo == null) {
                beanInfo = new Introspector(beanClass, null, USE_ALL_BEANINFO).getBeanInfo();
                synchronized (declaredMethodCache) {
                    context.putBeanInfo(beanClass, beanInfo);
                }
            }
            return beanInfo;
        }
    

    Introspector 的构造函数调用方法“findExplicitBeanInfo”来获取当前类的DeclaredMethods。然后用它的超类来做,直到 Object 或 stopClass。这里不会加载接口的方法。

    private Introspector(Class<?> beanClass, Class<?> stopClass, int flags)
                                            throws IntrospectionException {
        this.beanClass = beanClass;
    
        // Check stopClass is a superClass of startClass.
        if (stopClass != null) {
            boolean isSuper = false;
            for (Class<?> c = beanClass.getSuperclass(); c != null; c = c.getSuperclass()) {
                if (c == stopClass) {
                    isSuper = true;
                }
            }
            if (!isSuper) {
                throw new IntrospectionException(stopClass.getName() + " not superclass of " +
                                        beanClass.getName());
            }
        }
    
        if (flags == USE_ALL_BEANINFO) {
            explicitBeanInfo = findExplicitBeanInfo(beanClass);
        }
    
        Class<?> superClass = beanClass.getSuperclass();
        if (superClass != stopClass) {
            int newFlags = flags;
            if (newFlags == IGNORE_IMMEDIATE_BEANINFO) {
                newFlags = USE_ALL_BEANINFO;
            }
            superBeanInfo = getBeanInfo(superClass, stopClass, newFlags);
        }
        if (explicitBeanInfo != null) {
            additionalBeanInfo = explicitBeanInfo.getAdditionalBeanInfo();
        }
        if (additionalBeanInfo == null) {
            additionalBeanInfo = new BeanInfo[0];
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-02-01
      • 2016-09-09
      • 1970-01-01
      • 1970-01-01
      • 2020-11-13
      • 1970-01-01
      • 1970-01-01
      • 2019-12-30
      • 1970-01-01
      相关资源
      最近更新 更多