为什么我不应该使用不可变的 POJO 而不是 JavaBean?

发布于 2024-09-14 20:02:36 字数 1689 浏览 8 评论 0原文

我现在已经实现了一些 Java 应用程序,到目前为止只实现了桌面应用程序。我更喜欢使用不可变对象在应用程序中传递数据,而不是使用带有修改器(setter 和 getter)的对象(也称为 JavaBean)。

但在Java世界中,使用JavaBeans似乎更常见,我不明白为什么我应该使用它们。就个人而言,如果代码只处理不可变对象而不是一直改变状态,那么它看起来会更好。

第 15 项:最小化可变性有效的 Java 2ed 中也推荐使用不可变对象。

如果我有一个对象 Person 实现为 JavaBean ,它看起来像:

public class Person {
    private String name;
    private Place birthPlace;

    public Person() {}

    public setName(String name) {
        this.name = name;
    }

    public setBirthPlace(Place birthPlace) {
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

并且相同的 Person 实现为 不可变 > object:

public class Person {
    private final String name;
    private final Place birthPlace;

    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

或更接近 C 中的 struct :

public class Person {
    public final String name;
    public final Place birthPlace;

    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }
}

我还可以在不可变对象中使用 getter 来隐藏实现细节。但由于我只将它用作struct,我更喜欢跳过“getters”,并保持简单。

简而言之,我不明白为什么使用 JavaBeans 更好,或者我是否可以并且应该继续使用我的不可变 POJO?

许多 Java 库似乎对 JavaBean 都有更好的支持,但随着时间的推移,对不可变 POJO 的更多支持可能会变得更流行?

I have implemented a few Java applications now, only desktop applications so far. I prefer to use immutable objects for passing the data around in the application instead of using objects with mutators (setters and getters), also called JavaBeans.

But in the Java world, it seems to be much more common to use JavaBeans, and I can't understand why I should use them instead. Personally the code looks better if it only deals with immutable objects instead of mutate the state all the time.

Immutable objects are also recommended in Item 15: Minimize mutability, Effective Java 2ed.

If I have an object Person implemented as a JavaBean it would look like:

public class Person {
    private String name;
    private Place birthPlace;

    public Person() {}

    public setName(String name) {
        this.name = name;
    }

    public setBirthPlace(Place birthPlace) {
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

And the same Person implemented as an immutable object:

public class Person {
    private final String name;
    private final Place birthPlace;

    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

Or closer to an struct in C:

public class Person {
    public final String name;
    public final Place birthPlace;

    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }
}

I could also have getters in the immutable object to hide the implementation details. But since I only use it as a struct I prefer to skip the "getters", and keep it simple.

Simply, I don't understand why it's better to use JavaBeans, or if I can and should keep going with my immutable POJOs?

Many of the Java libraries seem to have better support for JavaBeans, but maybe more support for immutable POJOs gets more popular over time?

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

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

发布评论

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

评论(7

假装爱人 2024-09-21 20:02:36

首选 JavaBean 当

  • 您必须与期望它们的环境进行交互
  • 时,您有很多属性,在实例化时执行所有初始化会很不方便,
  • 您的状态很昂贵或由于某种原因无法复制,但需要
  • 您认为在某些时候 进行突变您可能必须更改属性的访问方式(例如,从存储值转移到计算值、访问授权等)
  • 您希望遵守编码标准,这些标准盲目地坚持使用 JavaBeans 更“面向对象” 更

喜欢不可变的 POJO 当

  • 您有少量简单的属性
  • 您不必与环境交互 假设 JavaBean 约定
  • 在克隆对象时很容易(或至少可能)复制状态
  • 您根本不打算克隆该
  • 对象非常确定您不必像上面那样修改属性的访问方式,
  • 您不介意听到关于您的代码如何不够“面向对象”的抱怨(或嘲笑)

Prefer JavaBeans When

  • you have to interact with environments that expect them
  • you have lots of properties for which it would be inconvenient to do all initialization on instantiation
  • you have state that is expensive or impossible to copy for some reason but requires mutation
  • you think at some point you may have to change how properties are accessed (e.g. moving from stored to calculated values, access authorization, etc.)
  • you want to conform to coding standards that mindlessly insist it is somehow more "object-oriented" to use JavaBeans

Prefer Immutable POJOs When

  • you have a small number of simple properties
  • you do not have to interact with environments assuming JavaBean conventions
  • it is easy (or at the very least possible) to copy state when cloning your object
  • you don't ever plan on cloning the object at all
  • you're pretty sure that you don't ever have to modify how properties are accessed as above
  • you don't mind listening to whining (or sneering) about how your code isn't sufficiently "object-oriented"
随风而去 2024-09-21 20:02:36

令我惊讶的是,Thread 这个词没有出现在本次讨论的任何地方。

不可变类的主要好处之一是,由于没有可变的共享状态,它们本质上更加线程安全。

这不仅使您的编码变得更容易,而且还会带来两个性能优势:

  • 减少同步需求。

  • 使用final变量的范围更大,可以方便后续的编译器优化。

我真的想转向不可变对象而不是 JavaBean 风格的类。通过 getter 和 setter 暴露对象的内部可能不应该是默认选择。

I was surprised that the word Thread did not appear anywhere in this discussion.

One of the main benefits of immutable classes is that they are inherently more thread safe due to no mutable, shared state.

Not only does this make your coding easier, it'll also give you two performance benefits as a side effect:

  • Less need for synchronization.

  • More scope for using final variables, which can facilitate subsequent compiler optimisations.

I am really trying to move towards immutable objects rather than JavaBean style classes. Exposing the guts of objects via getters and setters should probably not be the default choice.

ゃ懵逼小萝莉 2024-09-21 20:02:36

嗯,这取决于你想做什么。如果您使用持久层,并且从数据库中获取一些行到 POJO 中,并且想要更改属性并将其保存回来,那么使用 JavaBean 样式会更好,特别是如果您有很多属性。

考虑一下您的人,有很多字段,如名字、中间名、姓氏、出生日期、家庭成员、教育、工作、工资等。

而那个人恰好是一位刚刚结婚并接受拥有她的女性姓氏已更改,您需要更新数据库。

如果您使用不可变的 POJO,则获取代表她的 Person 对象,然后创建一个新的 Person 对象,将所有未按原样更改的属性以及新的姓氏传递给该对象,然后保存它。

如果它是一个 Java bean,您只需执行 setLastName() 并保存它。

这是“最小化可变性”而不是“从不使用可变对象”。在某些情况下,可变对象效果更好,您的工作就是决定使对象可变是否更适合您的程序。你不应该总是说“必须使用不可变对象”,而是在开始伤害自己之前看看你可以使多少个类成为不可变的。

Well it depends on what you're trying to do. If your working with a persistent layer, and you fetch some row from the database into a POJO, and you want to change a property and save it back, using JavaBean style would be better, especially if you have a lot of properties.

Consider that your person, has a lot of fields like, first, middle, last name, date of birth, family members, education, job, salary etc.

And that Person happens to be a female that just got married and accepted to have her last name changed, and you need to update the database.

If you're using immutable POJO, you fetch a Person object representing her, then you create a new Person object to which you pass all the properties that you didn't change as they are, and the new last name, and save it.

If it were a Java bean you can just do setLastName() and save it.

It's 'Minimize mutability' not 'never use mutable objects'. Some situations work better with mutable objects, it's really your job to decide if making an object mutable will better fit your program or not. You shouldn't always say 'must use immutable objects', instead see how many classes you can make immutable before you start hurting yourself.

友谊不毕业 2024-09-21 20:02:36

总结其他答案,我认为:

  • 不变性促进正确性(结构可以通过引用传递,并且您知道错误/恶意客户端不会破坏任何内容)和代码简单性
  • 可变性促进同质性 >:Spring 和其他框架创建一个不带参数的对象,设置对象属性,然后。使用同一类提供数据和保存修改也使界面更容易(您不需要 get(id): Clientsave(MutableClient),因为 MutableClient 是 MutableClient 的后代 人

如果有一个中间点(创建、设置属性、使不可变),也许框架会鼓励更多不可变的方法,

无论如何,我建议将不可变对象视为“只读 Java Bean”,强调一点,如果您是一个好的 。男孩,不要碰那个危险的 setProperty 方法,一切都会好起来的。

Summarizing other answers I think that:

  • Inmutability facilitates correctness (structs can be passed by reference and you know nothing will be destroyed by a faulty/malicious client) and code simplicity
  • Mutability facilitates homogeneity: Spring and other frameworks create an object with no arguments, set object properties, and voi là. Also make interfaces easier using the same class for giving data and saving modifications (you don't need get(id): Client and save(MutableClient), being MutableClient some descendant of Client.

If there were an intermediate point (create, set properties, make inmutable) maybe frameworks would encourage more an inmutable approach.

Anyway I suggest thinking in inmutable objects as "read only Java Beans" stressing the point that if you are a good boy and don't touch that dangerous setProperty method all will be fine.

花开雨落又逢春i 2024-09-21 20:02:36

从 Java 7 开始,您可以拥有不可变的 bean,这是两全其美的。在构造函数上使用注释@ConstructorProperties。

public class Person {
    private final String name;
    private final Place birthPlace;

    @ConstructorProperties({"name", "birthPlace"})
    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}

From Java 7 you can have immutable beans, the best of both worlds. Use the annotation @ConstructorProperties on your constructor.

public class Person {
    private final String name;
    private final Place birthPlace;

    @ConstructorProperties({"name", "birthPlace"})
    public Person(String name, Place birthPlace) {
        this.name = name;
        this.birthPlace = birthPlace;
    }

    public String getName() {
        return name;
    }

    public Place getBirthPlace() {
        return birthPlace;
    }
}
素罗衫 2024-09-21 20:02:36

老实说,我认为不可变的对象不会那么受欢迎。

我确实看到了这些优点,但是像 Hibernate 和 Spring 这样的框架目前非常流行(并且也有充分的理由),并且它们确实与 bean 配合得最好。

因此,我认为不变性并不是坏事,但它肯定会限制您与当前框架的集成选项。

编辑这些评论促使我稍微澄清一下我的答案。

毫无疑问,在某些问题领域,不变性非常有用,并且确实得到了使用。但我认为当前的默认值似乎是可变的,因为这是大多数人所期望的,并且只有在具有明显优势的情况下才是不可变的。

尽管确实可以在 Spring 中使用带有参数的构造函数,但它似乎旨在作为一种将遗留和/或第三方代码与漂亮的全新 Spring 代码一起使用的方式。至少这是我从文档中了解到的。

I don't think immutable objects will get all that popular, to be honest.

I do see the advantages, but frameworks like Hibernate and Spring are currently very much in vogue (and for a good reason too), and they really work best with beans.

So I don't think immutability is bad, but it would certainly limit your integration options with current frameworks.

EDIT The comments prompt me to clarify my answer a bit.

There most certainly are problem areas where immutability is very useful, and is indeed used. But I think the current default seems to be mutable as that is what is mostly expected, and only immutable if that has a clear advantage.

And though it is indeed possible to use constructors with arguments in Spring it seems to be intended as a way to use legacy and/or third party code with you beautiful brand-new Spring code. At least that's what I picked up from the documentation.

初心 2024-09-21 20:02:36

在 Java 编程方面是不可变的:一旦创建的东西就永远不会改变状态,无论是预期的还是意外的!

该技术在防御性编程中非常有用,其中另一个实体无法引起状态变化。

您不希望发生变化的示例:外部系统(单线程或多线程)从您的层获取引用并对对象进行操作并有意或无意地更改它。现在它可以是 POJO、集合或对象引用,并且您不希望对其进行更改或者希望保护数据。您肯定会让对象不可变作为防御技术

您期望更改的示例:实际上不需要不变性,因为它会阻碍正确的编程过程。

Immutable in terms of programming in Java : Something that once created should never have change of state , both expected or unexpected!

This technique is useful in defensive programming where another entity cannot induce change in the state.

Examples where you don't expect change : External systems(single or multi threaded) which gets reference from your layer and operates upon the object and knowingly or unknowingly change it. Now it could be a POJO or an collection or an object reference and you don't expect a change in it or you want to protect the data. You would definitely make the object immutable as defensive technique

Examples where you expect change : Really don't need immutability as it will obstruct in right programming procedures.

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