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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3511120/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 02:10:37  来源:igfitidea点击:

Why shouldn't I use immutable POJOs instead of JavaBeans?

javaimmutabilityjavabeanspojo

提问by Jonas

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.

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

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.

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

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

Item 15: Minimize mutability, Effective Java 2ed中也推荐不可变对象。

If I have an object Personimplemented as a JavaBeanit would look like:

如果我将一个对象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;
    }
}

And the same Personimplemented as an immutableobject:

同样Person作为不可变对象实现:

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 structin C:

或者更接近于structC:

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 structI prefer to skip the "getters", and keep it simple.

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

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

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

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

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

采纳答案by JUST MY correct OPINION

Prefer JavaBeans When

什么时候更喜欢 JavaBeans

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

Prefer Immutable POJOs When

首选不可变 POJO

  • 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"
  • 你有少量的简单属性
  • 您不必与假设 JavaBean 约定的环境进行交互
  • 克隆对象时很容易(或至少可能)复制状态
  • 你根本不打算克隆这个对象
  • 你很确定你不必像上面那样修改属性的访问方式
  • 你不介意听到抱怨(或冷笑)你的代码不够“面向对象”

回答by Benjamin Wootton

I was surprised that the word Threaddid 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.

  • 较少需要同步。

  • 使用 final 变量的空间更大,这可以促进后续的编译器优化。

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.

我真的试图转向不可变对象而不是 JavaBean 样式类。通过 getter 和 setter 暴露对象的内部结构可能不应该是默认选择。

回答by Andrei Fierbinteanu

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.

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

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.

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

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.

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

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

如果它是一个 Java bean,你可以执行 setLastName() 并保存它。

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.

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

回答by helios

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): Clientand save(MutableClient), being MutableClient some descendant of Client.
  • 不变性有助于正确性(结构可以通过引用传递,您知道错误/恶意客户端不会破坏任何内容)和代码简单性
  • 可变性有利于均匀性:Spring和其他框架建立,不带参数的对象,设置对象的属性,以及VOILà。还可以使用相同的类更轻松地提供数据和保存修改(您不需要get(id): Clientand save(MutableClient),作为 MutableClient 的某些后代 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.

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

回答by Larry

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

从 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;
    }
}

回答by extraneon

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.

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

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

所以我不认为不变性不好,但它肯定会限制您与当前框架的集成选项。

EDITThe 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.

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

回答by Rohitdev

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

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

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

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

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

你期望改变的例子:真的不需要不变性,因为它会阻碍正确的编程过程。