Java bean的setter许可是否会返回?

use*_*414 14 java design-patterns

我可以定义setter方法来返回它而不是void吗?

喜欢:

ClassA setItem1() {
      return this;
}

ClassA setItem2() {
      return this;
}
Run Code Online (Sandbox Code Playgroud)

然后我可以使用新的ClassA().setItem1().setItem2()

Rek*_*kin 14

关于JavaBeans规范存在很多误解.

它存在的主要原因是统一的Java"组件"模型.这是一种使用Reflection以编程方式与Java对象进行交互的方法.API本身名为JavaBeans Introspection.请看一下示例用法,您将比普通的Java程序员了解更多.

Introspection API可用于以统一的方式操作GUI元素.您的组件将其属性公开为一对getter和setter,以便可以在GUI构建器的属性表上在运行时发现和操作它们.

因此,在我看来,混合流畅的API和JavaBeans Spec是不行的.这是两个完全不相关的概念,可能会相互破坏.当方法签名不同(返回类型)时,JavaBeans内省可能不起作用.

看一下这个例子(摘自链接教程):

public class SimpleBean
{
private final String name = "SimpleBean";
private int size;

public String getName()
{
    return this.name;
}

public int getSize()
{
    return this.size;
}

public void setSize( int size )
{
    this.size = size;
}

public static void main( String[] args )
        throws IntrospectionException
{
    BeanInfo info = Introspector.getBeanInfo( SimpleBean.class );
    for ( PropertyDescriptor pd : info.getPropertyDescriptors() )
        System.out.println( pd.getName() );
}
}
Run Code Online (Sandbox Code Playgroud)

此示例创建一个非可视bean并显示从BeanInfo对象派生的以下属性:

  • 名称
  • 尺寸

您可能希望看到将void返回类型更改为其他任何内容时会发生什么.我已经这样做了,结果是一样的.那么,这是否意味着允许?

我不敢.JavaBeans规范对这些方法签名非常严格.事实上,实施是宽容的.尽管如此,我还是不喜欢将流畅的界面与JavaBeans混合在一起.你不能真正依赖它,如果发现现在有效,它也将在未来使用.

但是,从另一方面来看 - 看起来你并没有完全使用JavaBeans.只有getters/setters对方法.取决于您如何实施和设计您的API.

  • 你能引用JavaBeans规范的任何部分,它需要来自属性setter方法的void返回类型吗?我不是在寻找例子.我正在寻找规范的实际要求.第8.2节表明它不是*要求. (3认同)
  • 很好的样本,我很惊讶这实际上适用于非虚空的setter.需要注意的一点是,并非所有框架都使用Introspector,而是实现自己的逻辑.因此,当使用例如EL,jpa或jaxb时,您可能会得到不同的结果. (2认同)
  • 从Java 7开始,正在检查返回类型:http://stackoverflow.com/q/10806895/309259 (2认同)

Edw*_*rzo 13

JavaBeans技术规范描述了一种JavaBean作为:

Java Bean是可重用的软件组件,可以在构建器工具中以可视方式进行操作

他们需要在其他属性中提供内省,自定义,事件和持久性(第2.1节:什么是bean?)

通常使用JavaBeans规范(第7.1和8.3节)之后的访问器方法将"Java Bean"调用普通旧Java对象.事实是,这样的对象仍然远远不能满足所有要求.

如果您在此类中定义的对象实际上是JavaBean,那么您的方法必须根据JavaBean规范第7.1节返回void,其中访问器方法描述如下:

void setFoo(PropertyType value); // simple setter
PropertyType getFoo(); // simple getter
Run Code Online (Sandbox Code Playgroud)

第8.3节命名设计的属性模式说:

默认情况下,我们使用设计模式通过查找表单的方法来定位属性:

public <PropertyType> get<PropertyName>();
public void set<PropertyName>(<PropertyType> a);
Run Code Online (Sandbox Code Playgroud)

另外,对于布尔属性,我们允许getter方法匹配模式:

public boolean is<PropertyName>();
Run Code Online (Sandbox Code Playgroud)

但是,如果您的类只是一个POJO,那么使用您的方法链策略没有任何问题,因为您实际上不允许偏离规范,因为您实际上并没有构建JavaBean.并非你定义的所有类都应该是JavaBeans,对吧?

您可能希望了解Oracle JavaBeans教程.


Tom*_*rys 8

没理由你不能这样做.就个人而言,如果在对象创建过程中使用了setter,我会将它们命名为Item1()和withItem2().

ClassA obj = new ClassA().withItem1(item1).withItem2(item2);
Run Code Online (Sandbox Code Playgroud)

使得它更清楚(对我来说)方法的意图是什么.


Ale*_*øld 5

在检查Oracle JavaBean页面之后, 我没有发现任何明确告诉您设置器需要为空的东西。但是,所有示例都具有无效的设置方法。

Java API中的PropertyDescriptor支持非空的setter,所以我认为让setter返回这个应该是非常安全的。为了安全起见,您可能应该检查一下打算使用的框架是否使用了反射。例如,Spring在3.1之前的版本中支持xml config中的非void setter

  • 实际上,Java Beans规范的第7.1节(访问器方法)表明setter方法应该为空。(http://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html) (3认同)