convert a mutable object to an immutable object

狂风中的少年 提交于 2020-01-04 06:36:28

问题


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.

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.

Is there a way to alter the instance at runtime changing fields from non-final to final without subclassing etc.

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.

A nice tidy factory pattern might get the tick too...


回答1:


Joshua Bloch has addressed this problem in his book, Effective Java, Second Edition, in the second chapter on "Creating and Destroying Java Objects." 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();


来源:https://stackoverflow.com/questions/35213798/convert-a-mutable-object-to-an-immutable-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!