我可以定义setter方法来返回这个而不是void吗?
:
ClassA setItem1() {
return this;
}
ClassA setItem2() {
return this;
}
然后我可以使用新的ClassA(). setitem1 (). setitem2 ()
关于JavaBeans规范有很多误解。
它存在的主要原因是统一的Java"组件"模型。这是一种使用反射与Java对象进行编程交互的方法。API本身被命名为JavaBeans Introspection。请看看示例用法,您将比一般的Java程序员了解更多。
Introspection API可用于统一操作GUI元素。您的组件将其属性公开为一对getter和setter,以便可以在运行时在GUI构建器的属性表上发现和操作它们。
所以,在我看来,混合流畅的api和JavaBeans规范是不可能的。这是两个完全不相关的概念,可能会相互干扰。当方法签名不同(返回类型)时,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() );
}
}
这个例子创建了一个非可视bean,并显示了下列从BeanInfo对象派生的属性:
- 类
- <
- 名称/gh>大小
您可能想看看当您将void
返回类型更改为其他类型时会发生什么。我这样做了,结果是一样的。那么,这意味着它是允许的吗?
但是,从另一方面看,你似乎没有充分使用JavaBeans。只有getter/setter对方法。这取决于您如何实现和设计api。
JavaBean规范将JavaBean描述为:
Java Bean是一个可重用的软件可操作的组件可视化地在构建工具
它们需要在其他属性中提供自省、自定义、事件和持久性(第2.1节:什么是bean?)
使用JavaBeans规范(第7.1节和8.3节)的访问器方法调用普通旧Java对象的"JavaBean"是很常见的。事实是,这样的对象可能还远远不能满足所有的要求。
如果你在这个类中定义的对象实际上是一个JavaBean,那么你的方法必须返回void根据JavaBean规范,7.1节访问方法描述如下:
void setFoo(PropertyType value); // simple setter
PropertyType getFoo(); // simple getter
第8.3节命名为属性的设计模式说:
默认情况下,我们使用设计模式通过查找表单的方法来定位属性:
public <PropertyType> get<PropertyName>();
public void set<PropertyName>(<PropertyType> a);
此外,对于布尔属性,我们允许getter方法匹配以下模式:
public boolean is<PropertyName>();
然而,如果你的类只是一个POJO,那么使用你的方法链策略并没有什么错,因为你可以偏离规范,因为你实际上并没有构建一个JavaBean。毕竟,并不是所有定义的类都应该是JavaBeans,对吧?
你可能想看看Oracle JavaBeans教程。
你没有理由不这样做。我个人认为,如果在对象创建过程中使用setter,我会将它们命名为withItem1()和withItem2()。
ClassA obj = new ClassA().withItem1(item1).withItem2(item2);
使得(至少对我来说)这些方法的意图更清楚一些。
检查Oracle JavaBean页面后,我没有发现任何明确告诉您setter需要为空的内容。然而,所有的例子都有void set方法。
Java API中的PropertyDescriptor支持非void setter,所以我认为让你的setter返回this应该是相当安全的。为了安全起见,您应该检查一下您打算使用的框架是否使用了反射。例如,在3.1版本之前,Spring不支持xml配置中的非空setter。我猜这没有违反JavaBean规范,尽管我不确定。
请看下面的例子:
public class JavaBean {
private String value;
public String getValue() {
return value;
}
public JavaBean setValue(String value) {
this.value = value;
return this;
}
public static void main(String[] args) throws Exception {
JavaBean bean = new JavaBean();
JavaBean.class.getMethod("setValue", String.class).invoke(bean, "test");
System.out.println(bean.getValue());
}
}
许多框架使用反射API访问JavaBeans。正如你在上面看到的,访问返回"this"的setter不受返回类型的影响(返回类型不用于通过反射定位方法)。这也是有道理的,因为除了返回类型不同之外,在一个作用域中不可能有两个完全相同的方法。
只是补充一下,对于使用Spring 3.1+的人来说,这不再是一个问题了
看到http://static.springsource.org/spring/docs/3.1.0.M2/spring-framework-reference/html/new-in-3.1.html
是。这是一种比较常见的技术,叫做方法链接,可以用来创建一个"流畅的接口"。
参见:http://en.wikipedia.org/wiki/Method_chaining, http://en.wikipedia.org/wiki/Fluent_interface
绝对没有什么可以阻止你这样做,但是为什么呢?如果您想这样做,请创建一个接受参数的构造函数。请记住,一些使用bean的软件不期望返回值,可能会产生一些意想不到的结果
如果你只是想简化初始化(可能是设置测试),你可以使用一些groovy代码。
没有什么可以阻止你在接口中提供返回目标对象的setter方法…
但是,您还必须为Java Bean简单属性设置方法(例如void setProp(Type t)
)使用规范签名,否则Bean属性将无法被其他期望该签名的软件识别为可写。
Builder模式通常用于构造不可变对象。尽管JavaBeans本质上不是不可变的,但我经常在JavaBeans上使用构建器模式,因为它提供了一个流畅的接口,我可以在测试中使用它。两者很容易相互兼容,而不会破坏JavaBean规范。你可以在Effective Java
中的Builder Pattern中查看Stack Overflow。您只需要确保包含默认构造函数和私有Builder构造函数,然后将标准getter和setter放入JavaBean对象中。
这比构造函数链更清晰,也更容易阅读。