Immutable subclasses

2019-05-06 13:52发布

I'm currently developping a multithreaded framework. To avoid side effects, I would like to require that all data manipulated by the framewok has to be immutable.

So does a way exist in Java to specify I want all subclasses of a given class or all classes implementing a given interface to be immutable?

3条回答
手持菜刀,她持情操
2楼-- · 2019-05-06 14:32

To make a class truly immmutable, all members of the class must be immutable and the class itself must be final. This ensures the object cannot be changed from within the class or outside of the class.

To make members inside the class immutable, this means more than just making them final. For example

private final List<String> strings = new LinkedList<String>();

strings is final but can still be changed because items can be added and removed from the list. In this case, you could wrap it in an unmodifiable collection. Even this is not perfect though because the objects in your list could be mutable (Strings are not obviously, but your list might have mutable objects in them where you could do list.get(index).mutator(...))

There is no silver bullet as to how to make an object immutable. If it provides any methods that mutate the object, then it cannot be immutable.

As for making a class final, to achieve guaranteed immutability this necessary. Imagine the case,

class MyImmutableClass {
    private final String name
}

class MutableClass extends MyImmutableClass {
    private String mutableValue;

    public void setMutableValue(String mutableValue...)
}

void doSomething(MyImmutableClass c) {...}

There is no guarantee that doSomething is actually dealing with an immutable instance but rather it could be dealing with a mutable subclass. As you can see, this would pose a problem for working with interfaces. There is no way to guarantee that an implementor of an interface is immutable.

The @Immutable annotation does not guarantee immutability, but rather just states that the class is telling you it is immutable, but there is no good way to enforce that.

If you are able to work in groovy the @Immutable annotation has some effect as it does a lot of these techniques above that I mentioned. http://groovy.codehaus.org/Immutable+AST+Macro

查看更多
Luminary・发光体
3楼-- · 2019-05-06 14:49

I recommend looking into Mutability Detector. It performs static analysis to determine if a given class is immutable. It could be used to add something akin to a runtime assertion, i.e. you could choose to throw an exception if you are passed an instance of a mutable class. Note that it could analyse the actual, concrete class at runtime, including subclasses or implementations of an interface that you have defined.

It is still a pre-1.0 release, and has issues with java.lang.String, but it could be usable. If it's close to what you're looking for, but doesn't quite do what you want, I recommend contacting the mailing list or filing a bug report, as I believe the project maintainer is quite a reasonable guy. Disclaimer: that maintainer is me ;-)

查看更多
淡お忘
4楼-- · 2019-05-06 14:52

There is no way to require immutability of subclasses. You can make sure that subclasses of your classes do not mutate your state by not providing setters and keeping your instance variables private, but if subclasses declare their own instance variables, they have full control over them.

As far as interfaces go, the only thing you can do is to not provide setters. However, implementations can provide setters of their own.

查看更多
登录 后发表回答