简体   繁体   English

将可变对象转换为不可变对象

[英]convert a mutable object to an immutable object

I'd like to make a bean immutable and the traditional approach is to make all fields final and set their values in the constructor.我想让 bean 不可变,传统方法是将所有字段设为final并在构造函数中设置它们的值。

In my opinion this works well, unless there are many fields which need to be calculated interdependently via some complex logic or when multiple services need to take part in setting values.在我看来,这很有效,除非有许多字段需要通过一些复杂的逻辑相互依赖计算,或者当多个服务需要参与设置值时。

A factory is another approach but I can't come up with a tidy model that avoids too much code.工厂是另一种方法,但我无法提出避免过多代码的整洁模型。

What I'd like to do is create a mutable instance of the bean and once it is completely populated, I would like to "bake" it, ie make it immutable.我想做的是创建 bean 的可变实例,一旦它完全填充,我想“烘焙”它,即使其不可变。

Is there a way to alter the instance at runtime changing fields from non-final to final without subclassing etc.有没有办法在运行时更改实例,将字段从non-final更改为final而不需要子类化等。

I'm fairly certain it can't be done just using standard java/reflection but I suspect it might be possible using some byte-code alteration such as javassist or the like.我相当肯定它不能仅使用标准的 java/reflection 来完成,但我怀疑使用一些字节码更改(例如 javassist 等)可能是可能的。

A nice tidy factory pattern might get the tick too...一个漂亮整洁的工厂模式也可能会得到勾选......

Joshua Bloch has addressed this problem in his book, Effective Java, Second Edition , in the second chapter on "Creating and Destroying Java Objects." Joshua Bloch 在他的《 Effective Java, Second Edition》一书中关于“创建和销毁 Java 对象”的第二章中解决了这个问题。 You can view an example taken from his book here : 您可以在此处查看他的书中的示例

 // Builder Pattern public class NutritionFacts { private final int servingSize; private final int servings; private final int calories; private final int fat; private final int sodium; private final int carbohydrate; public static class Builder { // Required parameters private final int servingSize; private final int servings; // Optional parameters - initialized to default values private int calories = 0; private int fat = 0; private int carbohydrate = 0; private int sodium = 0; public Builder(int servingSize, int servings) { this.servingSize = servingSize; this.servings = servings; } public Builder calories(int val) { calories = val; return this; } public Builder fat(int val) { fat = val; return this; } public Builder carbohydrate(int val) { carbohydrate = val; return this; } public Builder sodium(int val) { sodium = val; return this; } public NutritionFacts build() { return new NutritionFacts(this); } } private NutritionFacts(Builder builder) { servingSize = builder.servingSize; servings = builder.servings; calories = builder.calories; fat = builder.fat; sodium = builder.sodium; carbohydrate = builder.carbohydrate; } }

An example to use this object is:使用此对象的示例是:

NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).calories(100).sodium(35).carbohydrate(27).build();

As you can see from the above example, you can create a mutable object first before building it into an immutable object.从上面的例子中可以看出,可以先创建一个可变对象,然后再将其构建为不可变对象。 The object's builder can also be adjusted and re-used to produce multiple, immutable objects.对象的构建器也可以调整和重用以生成多个不可变的对象。 For example:例如:

NutritionFacts.Builder food = new NutritionFacts.Builder(1, 1);
NutritionFacts salad = food.calories(100).build();
NutritionFacts bigMac = food.calories(1000).build();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM