开发者

Immutability after dependency injection, initialization

I'd like to be able to specify that an object's member variables are immutable once the object has been "initialized", which to me means after it has been injected with any dependencies, and has performed any other initialization operations that it can only perform after DI.

Are there languages that satisfy my interest - that formalize DI, initialization, and support immutability in this fashion? Maybe it's dumb to make them a part of a language; maybe not. I'm not sure.

Today I program in Java, but I can't use "f开发者_JAVA百科inal" nearly as much as I'd like, because those phases happen after the constructor has finished execution. Any advice on how to get what I want with Java? I guess I could have my objects implement a base class so that those phases happen before the constructor finishes, or use aspects to do the same.

Thoughts?


There are two main ways of producing immutable objects:

  1. use the builder/factory pattern - the builder may be mutable, but the objects it creates are immutable, usually implemented with final fields. You can also combine the two, so the object itself is used to build new instances, usually via "mutator" methods that change state on a separate, new instance. Spring's FactoryBean is an example of this.

  2. create a MutableObject subclass, which maintains a flag for mutable state. All your mutators check the mutable state before making any changes - if the object has been set to immutable, then the check throws an exception, otherwise the change goes ahead.

The first approach is quite Spring-centric, since it requires implmentation of a spring-specific interface. You can create factory beans that are regular beans, via factory-method/factory-bean attributes on a bean, which removes the spring dependency from your code.

Using the second approach is particularly useful with spring. You can instruct spring to call a method after bean initialization, e.g. seal() which seals the object - makes it immutable. Alternatively, you can implement a small BeanFactoryPostProcessor to do this automatically without having to remember to set the init-method="seal". on each immutable bean.


I guess it depends on what you want out of the immutability. If you want the guaranteed thread safety (where everything must be declared final, including the dependencies) then I think factory, builder or constructor injection are your only options.

If however you just want immutability of state, then declaring the state variables final should be enough. Even the immutable String class has a mutable field in its implementation (a cache of the hashcode value). As long as your code otherwise ensures that an instance is not available without injection, all should be well.


In Java, you can use a builder to initialize an immutable object in its constructor, so you'd shy away from setters.

If you use Scala, though, immutability is the default.


In Java, if you're using mutator methods to do your setting anyhow, it's pretty cheap (though also pretty ugly in my eyes) to add logic to prevent alterations once the object is initialized.

public void setMyProperty(String newValue) {
   checkInitialized();
   myProperty = newValue;
}

public void checkInitialized() {
   if ( initialized ) {
      throw new IllegalStateException("Setter called after initialization");
   }
}

At best though this is giving a dynamic check. It doesn't give you any static feedback over what you would have already had.


To specify that a class is immutable, you can use the @Immutable annotation.

You can see the Javadoc here.

This works well with the Findbugs plugin in Eclipse.

@Alexander:

As I understand him, he asked how to specify that a class is immutable. Not how to write an immutable class. This annotation can give you tool support to verify that you don't have a bug in your class that you claims are immutable.

A snippet from the Javadoc:

Of necessity this means that all public fields are final, and that all public final reference fields refer to other immutable objects

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜