Java Beans 的一个好的用例是什么?

What is a good use case of Java Beans?

我刚看到 Java Beans 规范。我觉得只使用 getter、setter 和空构造函数会使代码更加繁忙,而且开发人员需要管理轨道以正确设置所有必需的实例。

有人能给我指出一个使用这种设计的好用例吗?我无法感觉到它。我能想到一种用途 - "When you need to create an Instance of a class such that its data members will be decided later in the code."

编辑:伙计们,我不是在发起讨论。不想讨论advantages/disadvantages。我不是在寻找当前的库,例如 spring 等,这使得必须使用 Bean。我正在寻找一个示例来了解 Java bean 将带来的工程优势。 "Just one example where Java Beans design would help"

许多库和规范(例如 JPA、JavaEL)使用 Java Beans 规范并完全依赖于该行为。

使用 getters 和 setters 的优点是可以让您在这些方法中添加代码,例如创建 "virtual" 在运行时计算而不是存储在字段中的属性。

另外使用 getters 和 setters 允许其他框架包装这些方法并提供其他功能,如更改日志记录等。在许多情况下,这是通过在内部创建子类并覆盖getters 和 setters。用户不会注意到,因为 "weaving" 或 "proxying" 通常在运行时完成。例如,当您调用 getter 访问相关集合或实体时,Hibernate 使用它来提供延迟加载功能。

更新:

根据请求 "virtual" 属性的示例:

假设您有一个 Person bean,它具有字段 firstNamelastName。您可以通过提供以下 getter:

添加只读虚拟 属性 name
public String getName() {
  return getFirstName() + " " + getLastName();
}

更新二:

关于为什么需要 getters 和 setters 的另一个说明:这基本上来自 Java 的工作原理。直接支持属性的语言(如 C#)允许您编写 person.firstName = "Joe"; 之类的代码,并且如果存在 setter 则仍然使用 setter,或者如果 属性 是只读的则抛出错误。因此,如果您为 firstName 添加 setter,这些语言将在内部将 firstName = "Joe" 翻译为 setFirstName("Joe"),而开发人员无需更改任何内容 - 非常优雅的解决方案。 :)

由于 Java 不支持,我们必须始终提供访问器方法 (setters/getters),即使它们没有做任何特殊的事情 - 以防万一它们 以后可能需要更改。

如上所述,JavaBeans 可以用作 DAO(数据访问对象),用于检索数据并将数据保存到(SQL 主要是)数据库。它们在您真正关心的是数据的地方很有用

getters & setters 确保 the basic object oriented concept - Encapsulation

Imagine you wrote the code for a class and another dozen programmers from your company all wrote programs that used your class. So , anyone can change your instance variable & it may harm your code .

所以你应该

Keep instance variables protected(带有 access modifier, often private)。

制作public accessor methods,并强制调用代码使用这些方法 rather than directly accessing the instance variable

他们的代码导致您的代码出错。

看下面的例子

public class MyClass{
public int size;
public int weight;
...
}
public class OthersClass {
public static void main (String [] args) {
MyClass myClass= new MyClass();
myClass.size = -5; // Legal but bad logic
}
}

需要一个空的构造函数来通过持久性框架的反射创建一个新实例。如果您不为 class 提供任何带参数的额外构造函数,则无需提供空构造函数,因为您默认获得一个。

根据我的经验,这是为了防止有人添加带参数的构造函数,从而有效地删除默认构造函数的情况。通过显式实现默认构造函数,这种情况不太可能发生。

另外,我猜你想像一个 class 有很多属性,只用 getter 和 setter 很难填充,但也要注意以下几点:

  • Getters 将自动化视图部分。
  • Setter 将允许您在必要时添加验证或错误控制。

很多人会告诉您 Java Beans 比使用充当 "data transfer objects" 的普通 Java 对象要好得多。

但是其他人,例如这个人在他著名的书中 https://cleansourcecode.files.wordpress.com/2013/10/clean-code.pdf 表明大多数情况下,"beans" 和 getter 以及 setter 确实 没有太多额外的 值(整个第 6 章都专门讨论这个问题).

所以你应该自己决定(也可能和你的队友一起)如果你的问题用 "Java Beans" 或 "plain data transfer objects" 更好地解决。

当然,"beans" 强制您使用 setters,这允许您稍后添加验证。另一方面:这样的更改会修改您的方法的 语义 ;突然 setter 进行验证并开始抛出异常可能是完全错误的。因为,如果您更改方法的 contract;你可能不想在幕后暗中这样做。

除了 JavaBeans 规范的实际优点和缺点之外,我认为重要的是要记住它是 1996 年引入的规范,用于启用 Java 代码的可视化编辑。

我不知道这种编程方法是否成功并被采用(我个人从未使用过)。我所知道的是该规范继续存在并得到非常广泛的应用(恕我直言,有时在不是最合适的情况下)。

我认为可以使用 JavaBeans 的最有用的地方是 框架 。一个很好的例子是 Spring。 JavaBean class 非常适用于 class 实例化不由程序员负责,而是委托给应用程序容器(例如通过反射)的情况。