Java bean 的 setter 是否允许返回此值?

发布于 2024-11-02 12:25:23 字数 214 浏览 0 评论 0 原文

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

就像:

ClassA setItem1() {
      return this;
}

ClassA setItem2() {
      return this;
}

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

can I define setter method to return this rather than void?

Like:

ClassA setItem1() {
      return this;
}

ClassA setItem2() {
      return this;
}

then I can use new ClassA().setItem1().setItem2()

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

护你周全 2024-11-09 12:25:23

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

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

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

因此,在我看来,混合使用 Fluent 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() );
}
}

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

  • 大小

您可能想看看更改 void 返回类型为其他任何内容。我已经这样做了,结果是一样的。那么,这是否意味着这是允许的?

恐怕不行。 JavaBeans 规范对这些方法签名非常严格。只是碰巧实施是宽容的。尽管如此,我不建议将流畅的接口与 JavaBean 混合。你不能真正相信这一点,如果这个发现现在有效,那么将来也同样有效。

但是,从另一方面来看 - 看起来您没有充分使用 JavaBeans。只有 getter/setter 对方法。如何实现和设计 API 由您决定。

There is a lot of misunderstanding about JavaBeans spec.

The main reason for it's existence is the unified Java "component" model. It's a way to interact programatically with a Java Object using Reflection. The API itself is named JavaBeans Introspection. Please, take a look at example usages and You will know a lot more than an average Java programmer does.

Introspection API can be used to manipulate GUI elements in an unified manner. Your component exposes it's properties as a pairs of getters and setters so that they could be discovered and manipulated at run-time on a GUI builder's property sheet.

So, mixing fluent APIs and JavaBeans Spec in my opinion is a no-go. That's two completely unrelated concepts and can disrupt each other. JavaBeans Introspection might not work when method signature differs (return type).

Take a look at this example (taken from linked tutorial):

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() );
}
}

This example creates a non-visual bean and displays following properties derived from the BeanInfo object:

  • class
  • name
  • size

You might want to see what happens when You change void return type to anything else. I have done so and the result is the same. So, does that mean it's allowed?

I'm afraid no. The JavaBeans spec is quite strict about those method signatures. It just happened that implementation is forgiving. Nonetheless, I'd disadvise mixing fluent interface with JavaBeans. You can't really rely that, if the discovery works now, it will also in future.

But, from the other side - it looks like You don't use JavaBeans to full extent. Only the getters/setters pair of method. It's up to You how You implement and design Your APIs.

辞别 2024-11-09 12:25:23

JavaBeans 规范 将 JavaBean 描述为:

Java Bean 是可重用的软件
可操作的组件
在构建器工具中直观地显示

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

通常使用以下访问器方法将“Java Bean”调用为普通旧 Java 对象JavaBeans 规范(第 7.1 和 8.3 节)。事实是,这样的对象可能仍远未满足所有要求。

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

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。毕竟,并非您定义的所有类都应该是 JavaBean,对吧?

您可能想查看 Oracle JavaBeans 教程

The JavaBeans Specification describes a JavaBean as:

A Java Bean is a reusable software
component that can be manipulated
visually in a builder tool

They are required to provide introspection, customization, events and persistence among other properties (Section 2.1: What is a bean?)

It is common to call a "Java Bean" to a Plain Old Java Object with accessor methods following the JavaBeans Specification (Section 7.1 and 8.3). The truth is that such object could still be far from being compliant with all the requirements.

If the object your are defining in this class is actually a JavaBean then your method must return void according to JavaBean Specification, section 7.1 where accessor methods are described as follows:

void setFoo(PropertyType value); // simple setter
PropertyType getFoo(); // simple getter

The section 8.3 named designed patterns for properties says:

By default, we use design patterns to locate properties by looking for methods of the form:

public <PropertyType> get<PropertyName>();
public void set<PropertyName>(<PropertyType> a);

In addition, for boolean properties, we allow a getter method to match the pattern:

public boolean is<PropertyName>();

However, if your class is just a POJO then there is nothing wrong with using your method chaining strategy because you are allowed to deviate from the specification since you are not actually building a JavaBean. Not all the classes you define are supposed to be JavaBeans after all, right?

Your might like to take a look at the Oracle JavaBeans Tutorial.

渡你暖光 2024-11-09 12:25:23

没有理由你不能这样做。就我个人而言,如果在对象创建期间使用 setter,我会将它们命名为 withItem1() 和 withItem2()。

ClassA obj = new ClassA().withItem1(item1).withItem2(item2);

让它更清楚(无论如何对我来说)这些方法的意图是什么。

No reason you couldn't do that. Personally, if the setters are being used during object creation, I'd name them withItem1() and withItem2().

ClassA obj = new ClassA().withItem1(item1).withItem2(item2);

Makes it a bit clearer (to me anyway) what the intent of the methods are.

一花一树开 2024-11-09 12:25:23

检查 Oracle JavaBean 页面后,我没有找到任何明确告诉您setter 必须为空。尽管如此,所有示例都有 void set-methods。

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

After checking the Oracle JavaBean pages I didn't find anything which explicitly tells you that the setters need to be void. Nevertheless all examples have void set-methods.

The PropertyDescriptor in the Java API support non-void setters, so I think it should be pretty safe to let your setters return this. To be on the safe side you should probably check out if the frameworks you intend to use that uses reflection. For instance didn't Spring support non-void setters in xml config prior to version 3.1.

一念一轮回 2024-11-09 12:25:23

我猜想这并不违反 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 访问 JavaBean。正如您在上面所看到的,访问返回“this”的 setter 不受返回类型的影响(返回类型不用于通过反射定位方法)。这也是有道理的,因为一个作用域中不能有两个除了返回类型之外完全相同的方法。

I would guess this is not in violation of the JavaBean specification, although I am not sure of it.

Check out the following example:

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());
    }
}

Many frameworks access JavaBeans using the reflection API. As you can see above, accessing a settter which returns 'this' is not influenced by the return type (the return type is not used to locate a method via reflection). It also makes sense, because you cannot have two methods in one scope that are identical except for their return type.

命硬 2024-11-09 12:25:23

只是补充一下,对于使用 Spring 3.1+ 的人来说,这不再是问题了,

请参阅
http:// /static.springsource.org/spring/docs/3.1.0.M2/spring-framework-reference/html/new-in-3.1.html

Just to add that for people using Spring 3.1+ this is not an issue anymore

see
http://static.springsource.org/spring/docs/3.1.0.M2/spring-framework-reference/html/new-in-3.1.html

落在眉间の轻吻 2024-11-09 12:25:23

是的。这是一种称为方法链接的常见技术,可用于创建“流畅的界面”。

请参阅:http://en.wikipedia.org/wiki/Method_chaininghttp://en.wikipedia.org/wiki/Fluent_interface

Yes. This is a somewhat common technique called Method Chaining, and can be used to create a "fluent interface".

See: http://en.wikipedia.org/wiki/Method_chaining, http://en.wikipedia.org/wiki/Fluent_interface

萤火眠眠 2024-11-09 12:25:23

绝对没有什么可以阻止你这样做,但为什么。如果您想这样做,请创建一个采用参数的构造函数。请记住,某些使用 bean 的软件不会期望返回值,并且可能会产生一些意外的结果。

如果您只是想简化初始化(也许是为了设置测试),您可以使用一些常规代码。

Absolutely nothing to stop you doing that but why. If you want to do this create a constructor that takes the args. Bare in mind some software that uses beans would not be expecting return values and may have some unexpected results

If you just want to simplify initialisation, (maybe to set up tests) you could use some groovy code.

淡水深流 2024-11-09 12:25:23

没有什么可以阻止您提供 setter 方法,这些方法返回目标对象作为界面中的约定...

但是,您还必须使用 Java Bean 简单属性 setter 方法(例如 void setProp(Type t))或bean 属性将不能被需要该签名的其他软件识别为可写。

There is nothing preventing you from providing setter methods which return the target object as a convention in your interface...

However, you must also use the canonical signature for Java Bean Simple Property setter methods (e.g. void setProp(Type t)) or the bean property will not be recognized as writeable by other software which expects that signature.

翻身的咸鱼 2024-11-09 12:25:23

Builder 模式通常用于构造不可变对象。尽管 JavaBean 本质上不是一成不变的,但我经常在 JavaBean 上使用构建器模式,因为它提供了一个可以在测试中使用的流畅接口。两者很容易相互兼容,而不破坏JavaBean规范。您可以在 Stack Overflow 上查看 Effective Java 中的构建器模式

您只需要确保您包含默认构造函数以及私有 Builder 构造函数,然后将标准 getter 和 setter 放入 JavaBean 对象中。

这比构造函数链干净得多,也更容易阅读。

The Builder pattern is generally used for constructing immutable objects. Even though JavaBeans by nature aren't immutable, I have frequently used the builder pattern on my JavaBeans because it provides a fluent interface that I can use in my tests. The two are easily compatible with each other without breaking the JavaBean specification. You can check out it out on Stack Overflow at Builder Pattern in Effective Java

You just need to make sure you include a default constructor as well as the private Builder constructor, and then put your standard getters and setters in the JavaBean object.

This is much cleaner than constructor chaining, and easier to read as well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文