Do effectively immutable objects make sense? - java

In the book Java Concurrency In Practice it explains the advantages of "effectively immutable" objects versus mutable objects concurrency-wise. But it does not explain what advantage "effectively immutables" objects would offer over really immutable objects.
And I don't get it: can't you always build a really immutable object at the moment you'd decide to publish safely an "effectively immutable" object? (instead of doing your "safe publication" you'd build a really immutable object and that's it)
When I'm designing classes I fail to see cases where I couldn't always build a truly immutable object (using delegation if needed etc. to build other wrapped objects, themselves truly immmutable of course) at the moment I'd decide to "safely publish".
So are "effectively immutable" object and their "safe publication" just a case of bad design or poor APIs?
Where would you be forced to use an effectively immutable object and be forced to safely publish it where you couldn't build a much superior really immutable object?

Yes, they make sense in some cases. An easy example is when you want some property to be generated lazily and cached so you can avoid the overhead of generating it if it's never accessed. String is an example of an effectively immutable class that does this (with its hashcode).

For circular immutables:
class Foo
{
final Object param;
final Foo other;
Foo(Object param, Foo other)
{
this.param = param;
this.other = other;
}
// create a pair of Foo's, A=this, B=other
Foo(Object paramA, Object paramB)
{
this.param = paramA;
this.other = new Foo(paramB, this);
}
Foo getOther(){ return other; }
}
// usage
Foo fooA = new Foo(paramA, paramB);
Foo fooB = fooA.getOther();
// publish fooA/fooB (unsafely)
A question is, since this of fooA is leaked inside constructor, is fooA still a thread safe immutable? That is, if another thread reads fooB.getOther().param, is it guaranteed to see paramA? The answer is yes, since this is not leaked to another thread before the freeze action; we can establish hb/dc/mc orders required by spec to prove that paramA is the only visible value for the read.
Back to your original question. In practice there are always constraints beyond the pure technical ones. Initialize everything inside constructor is not necessarily the best option for a design, considering all engineering, operational, political and other human-ish reasons.
Ever wondering why we are fed to think that it is a great supreme idea?
The deeper problem is Java lacks a general cheap fense for safe publication which is cheaper than volatile. Java only has it for final fields; for some reason, that fence is not available otherwise.
Now final carries two independent meanings: 1st, that a final field must be assigned exactly once; 2nd, the memory semantics of safe publication. These two meanings have nothing to do with each other. It is quite confusing to bundle them together. When people need the 2nd meaning, they are forced to accept the 1st meaning too. When the 1st is very inconvenient to achieve in a design, people wonder what they have done wrong - not realizing that it's Java that did wrong.
Bundling of two meanings under one final makes it double plus good, so that apparently we have more reason and motivation to use final. The more sinister story is actually we are forced to use it because we are not given a more flexible choice.

Using effectively immutable objects lets you avoid creating a considerable number of classes. Instead of making pairs of [mutable builder]/[immutable object] classes, you can build one effectively immutable class. I usually define an immutable interface, and a mutable class that implements this interface. An object is configured through its mutable class methods, and then published through its immutable interface. As long as the clients of your library program to the interface, to them your objects remain immutable through their published lifetime.

Suppose one has an immutable class Foo with five properties, named Alpha, Beta, etc., and one wishes to provide WithAlpha, WithBeta, etc. methods which will return an instance which is identical to the original except with the particular property changed. If the class is truly and deeply immutable, the methods have to take the form:
Foo WithAlpha(string newAlpha)
{
return new Foo(newAlpha, Beta, Gamma, Delta, Epsilon);
}
Foo WithBeta(string newBeta)
{
return new Foo(Alpha, NewBeta, Gamma, Delta, Epsilon);
}
Ick. A massive violation of "Don't Repeat Yourself" (DRY) principles. Further, adding a new property to the class would require adding it to every single one of those methods.
On the other hand, if each Foo held an internal FooGuts which included a copy constructor, one could instead do something like:
Foo WithAlpha(string newAlpha)
{
FooGuts newGuts = new FooGuts(Guts); // Guts is a private or protected field
newGuts.Alpha = newAlpha;
return new Foo(newGuts); // Private or protected constructor
}
The number of lines of code for each method has increased, but the methods no longer need to make any reference to any properties they aren't "interested" in. Note that while a Foo might not be immutable if its constructor were called with a FooGuts to which any outside reference existed, its constructor is only accessible to code which is trusted not to maintain any such reference after construction.

Related

Does Java have a concept of reference ownership or noncopyable classes?

I would like to have some guarantee that instances of some particular class Content is only accessed by its "owner", and if another object wants the same Content it needs to take a deep copy. Coming from C++ I would achieve that using a unique_ptr, is there anything similar in Java?
Currently I am resolving this by just keeping the Content private everywhere I keep one and paying attention to creating a new Content (the constructor implements the deep copy mechanism) on a getContent. But I have no means of enforcing possible other users of the Content class to follow the same pattern, it's easy to forget. It would be nicer if it could take care of itself somehow, like not being copyable.
I realize that it goes somewhat against the spirit of the language, but in some cases I think it's justified. For example, if Content represents some stream of data that is modified even by reading it. I thought, if not in the core language, maybe there is some #interface for compile-time checking or a way of creating one?
Edit: The idea is that the owner can modify the object freely, before or after taking copies, and if someone takes a deep copy, they can modify theirs (not affecting the original), so making the Content immutable is a bit too harsh (unless I'm misunderstanding what that implies).
There are a couple of common strategies here:
Privacy with defensive copying
In this strategy, you'd have the owner have a private reference to the content, and if it's appropriate for it to give out copies of that content, to do so via a defensive copy:
class Owner {
private Content content;
// ...unnecessary detail omitted...
public Content getContent() {
return new Content(this.content);
}
}
The Cloneable interface can sometimes be useful here.
Immutable objects
The other common strategy is to use immutable objects (e.g., ensure that Content, once instantiated, cannot be modified). Then you don't care who has a reference to the content, since they cannot change it.
No there isn't.
Once you have established a reference to an object, there's absolutely nothing you can do to stop someone form assigning another reference to that object via that established reference.
Java programmers get round this by making objects immutable (see java.lang.String). Then you ought not give two hoots about who else is referring to a particular instance.
You can declare the class Content as Immutable by doing this:
Don't provide "setter" methods — methods that modify fields or objects referred to by fields.
Make all fields final and private.
Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final.
If the instance fields include references to mutable objects, don't allow those objects to be changed
Here is a java official doc: https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html
Java does not have something like that. There are some language elements that can help with such requirements:
Enums that have only one constant; to be used as "built-in" singletons
Methods in Collections to create immutable copies of collections
And of course, you can make all fields in your class final; so they get initialized only during construction time; to prevent later changes
But as Java is also missing a const concept, you can partially work around such things. Like in:
class Foo {
private final List<Bar> bars = new ArrayList<>();
doesn't mean that instances of Foo will be immutable - as you still can add/remove elements to that list owned by Foo.
Similar; given
List<Foo> root = ...
List<Foo> immutableCopy = Collections.unmodifiableList(root);
one can still change that immutableCopy ... by messing up root.

Need I make all classes immutable?

I read Effective Java, and there written
If a class cannot be made immutable, limit its mutability as much as
possible...
and
...make every field final unless there is a compelling reason to make it
nonfinal.
So need I always make all my POJO(for example simple Bookclass with ID, Title and Author fields) classes immutable? And when I want to change state of my object(for example user change it in table where represented many Books), instead of setters use method like this:
public Book changeAuthor(String author) {
return new Book(this.id, this.title, author); //Book constructor is private
}
But I think is really not a good idea..
Please, explain me when to make a class immutable.
No, you don't need always to make your POJO immutable. Like you said, sometimes it can be a bad idea. If you object has attributes that will change over the time, a setter is the most comfortable way to do it.
But you should consider to make your object immutable. It will help you to find errors, to program more clearly and to deal with concurrency.
But I think you quoting say everything:
If a class cannot be made immutable, limit its mutability as much as
possible...
and
...make every field final unless there is a compelling reason to make
it nonfinal.
That's what you should do. Unless it's not possible, because you have a setter. But then be aware of concurrency.
In OOP world we have state. State it's all properties in your object. Return new object when you change state of your object guaranties that your application will work correctly in concurrent environment without specific things (synchronized, locks, atomics, etc.). But you always create new object.
Imagine that your object contains 100 properties, or to be real some collection with 100 elements. To follow the idea of immutability you need copy this collection as well. It's great memory overhead, perhaps it handled by GC. In most situation it's better to manually handle state of object than make object immutable. In some hard cases better to return copy if concurrent problems very hard. It depends on task. No silver bullet.
1. A POJO is one which has private Instance Variables with Getter and Setter methods.
2. And Classes like String class, which needs a constant behavior/implementation at all time needs to be
final, not the one which needs to change with time.
3. For making a class immutable, final is not only the solution, One can have private Instance variables, with only Getter methods. And their state being set into the Constructor.
4. Now depending on your coding decision, try to rectify which fields needs to be constant throughout the program, if you feel that certain fields are to be immutable, make them final.
5. JVM uses a mechanism called Constant folding for pre-calculating the constant values.

Do fields need to be explicitly final to have a "proper" immutable object?

You often read about immutable objects requiring final fields to be immutable in Java. Is this in fact the case, or is it simply enough to have no public mutability and not actually mutate the state?
For example, if you have an immutable object built by the builder pattern, you could do it by having the builder assign the individual fields as it builds, or having the builder hold the fields itself and ultimately return the immutable object by passing the values to its (private) constructor.
Having the fields final has the obvious advantage of preventing implementation errors (such as allowing code to retain a reference to the builder and "building" the object multiple times while in fact mutating an existing object), but having the Builder store its data inside the object as it is built would seem to be DRYer.
So the question is: Assuming the Builder does not leak the Object early and stops itself from modifying the object once built (say by setting its reference to the object as null) is there actually anything gained (such as improved thread safety) in the "immutability" of the object if the object's fields were made final instead?
Yes, you do get "thread safety" from final fields. That is, the value assigned to a final field during construction is guaranteed to be visible to all threads. The other alternative for thread safety is to declare the fields volatile, but then you are incurring a high overhead with every read… and confusing anyone who looks at your class and wonders why the fields of this "immutable" class are marked "volatile."
Marking the fields final is the most correct technically, and conveys your intent most clearly. Unfortunately, it does make the builder pattern very cumbersome. I think it should be possible to create an annotation processor to synthesize a builder for an immutable class, much like Project Lombok does with setters and getters. The real work would be the IDE support needed so that you could code against the builders that don't really exist.
An Object can certainly have mutable private fields and still work as an immutable object. All that matters to meet the contract of immutability is that the object appears immutable from the outside. An object with non-final private fields but no setters would for example satisfy this requirement.
In fact, if your encapsulation is right then you can actually mutate the internal state and still operate successfully as an "immutable" object. An example might be some sort of lazy evaluation or caching of data structures.
Clojure for example does this in its internal implementation of lazy sequences, these objects behave as if they are immutable but only actually calculate and store future values when they are directly requested. Any subsequent request retrieves the stored value.
However - I would add as a caveat that the number of places where you would actually want to mutate the internals of an immutable object are probably quite rare. If in doubt, make them final.
I think you would just need to consider the environment its running in and decide if frameworks that use reflection to manipulate objects are a hazard.
One could easily cook up an oddball scenario where a supposedly immutable object gets clobbered via a POST injection attack because of a web binding framework that's configured to use reflection instead of bean setters.
You definitely can have an immutable object with non-final fields.
For example see java 1.6 implementation of java.lang.String.
Comment:
#erickson
Like that:
class X { volatile int i, j; }
X y;
// thread A:
X x = new X;
x.i = 1;
x.j = 2;
y = x;
// thread B:
if (y != null) {
a = y.i;
b = y.j;
}
?

Defensive copy: should it be specified in the Javadoc?

as far as I understand, getters/setters should always make copies, in order to protect the data.
However, for many of my classes, it is safe to have the getter return a reference to the property asked for, so that the following code
b = a.getB();
b.setC(someValue);
actually changes the state of object a. If I can prove that it is OK for my class, is it good practice to implement the getter this way? Should the user then be notified of this, for example in the Javadoc? I think that this would break the implementation-hiding paradigm, so, should I always assume that the state of a did not change, and make a call to the setter
b = a.getB();
b.setC(someValue);
a.setB(b);
Thanks in advance
S
There's a good argument in your above example that since A is maintaining a reference to B, A should look after B, and not hand it out but manipulate it on your behalf. Otherwise you can argue that you're breaking encapsulation (since A reveals it has a reference to B), and ideally objects should do things for you, rather than export their contents such that you can manipulate them.
Having said all that, the above is certainly not an uncommon practise and often a pragmatic choice.
When you expose an object via get(), you have three options:
expose the actual object
make a defensive copy
expose an object that wraps the original, but prohibits modification. e.g. you can wrap the original object in a restricted interface. See (for example) Collections.unmodifiableCollection() which wraps the original collection (and doesn't copy it) but provides an interface that doesn't permit modification.
Whatever you do, you should document it in the interface (and hence in the Javadoc). Otherwise you're at liberty to change it later, and dependent code can easily break.
Well, the setC violates the Law of Demeter, so I don't think I'd call it a best practice. ("Law" is a bit strong - for instance, it's generally not applied to fluent interfaces.)
That said, getters should not always make copies IMHO. Doing a deep clone can be expensive. There are other options, such as immutable objects.
And, realistically, there are pragmatic considerations.
But I'd err on the side of TMI (too much information) in the JavaDoc.
A further option not yet mentioned is to expose the object via an immutable interface. Obviously this isn't fool-proof as the calling code could always downcast the object into the mutable version, but it avoids any overhead in wrapping the object or creating a copy.
I usually take this approach if I'm writing an API that I'm likely to use myself or within my programming team; i.e. where I know "clients" are going to be good citizens!
// Immutable interface definition.
public interface Record {
String getContent();
}
// Mutable implementation of Record interface.
public class MutableRecord implements Record {
private final String content;
public MutableRecord(String content) {
this.content = content;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
// API that only exposes the object via its Record interface.
public class MyApi {
private final MutableRecord mutableRecord;
public Record getRecord() {
return mutableRecord;
}
}
You will get copying wrong before you know it! And then you have a real bug, not a potential one.
Therefore, if you trust the client code, don't bother about it.
This is highly academic and I personally never had a problem with it. I also immediately turn the check off in FindBugs (Java) for example...
And unless there is a problem, who reads JavaDoc and the like anyway? Anybody out there?

Java: Rationale of the Object class not being declared abstract

Why wasn't the java.lang.Object class declared to be abstract ?
Surely for an Object to be useful it needs added state or behaviour, an Object class is an abstraction, and as such it should have been declared abstract ... why did they choose not to ?
An Object is useful even if it does not have any state or behaviour specific to it.
One example would be its use as a generic guard that's used for synchronization:
public class Example {
private final Object o = new Object();
public void doSomething() {
synchronized (o) {
// do possibly dangerous stuff
}
}
}
While this class is a bit simple in its implementation (it isn't evident here why it's useful to have an explicit object, you could just declare the method synchronized) there are several cases where this is really useful.
Ande, I think you are approaching this -- pun NOT intended -- with an unnecessary degree of abstraction. I think this (IMHO) unnecessary level of abstraction is what is causing the "problem" here. You are perhaps approaching this from a mathematical theoretical approach, where many of us are approaching this from a "programmer trying to solve problems" approach. I believe this difference in approach is causing the disagreements.
When programmers look at practicalities and how to actually implement something, there are a number of times when you need some totally arbitrary Object whose actual instance is totally irrelevant. It just cannot be null. The example I gave in a comment to another post is the implementation of *Set (* == Hash or Concurrent or type of choice), which is commonly done by using a backing *Map and using the Map keys as the Set. You often cannot use null as the Map value, so what is commonly done is to use a static Object instance as the value, which will be ignored and never used. However, some non-null placeholder is needed.
Another common use is with the synchronized keyword where some Object is needed to synchronize on, and you want to ensure that your synchronizing item is totally private to avoid deadlock where different classes are unintentionally synchronizing on the same lock. A very common idiom is to allocate a private final Object to use in a class as the lock. To be fair, as of Java 5 and java.util.concurrent.locks.Lock and related additions, this idiom is measurably less applicable.
Historically, it has been quite useful in Java to have Object be instantiable. You could make a good point that with small changes in design or with small API changes, this would no longer be necessary. You're probably correct in this.
And yes, the API could have provided a Placeholder class that extends Object without adding anything at all, to be used as a placeholder for the purposes described above. But -- if you're extending Object but adding nothing, what is the value in the class other than allowing Object to be abstract? Mathematically, theoretically, perhaps one could find a value, but pragmatically, what value would it add to do this?
There are times in programming where you need an object, some object, any concrete object that is not null, something that you can compare via == and/or .equals(), but you just don't need any other feature to this object. It exists only to serve as a unique identifier and otherwise does absolutely nothing. Object satisfies this role perfectly and (IMHO) very cleanly.
I would guess that this is part of the reason why Object was not declared abstract: It is directly useful for it not to be.
Does Object specify methods that classes extending it must implement in order to be useful? No, and therefor it needn't be abstract.
The concept of a class being abstract has a well defined meaning that does not apply to Object.
You can instantiate Object for synchronization locks:
Object lock = new Object();
void someMethod() {
//safe stuff
synchronized(lock) {
//some code avoiding race condition
}
}
void someOtherMethod() {
//safe code
synchronized(lock) {
//some other stuff avoiding race condition
}
}
I am not sure this is the reason, but it allows (or allowed, as there are now better ways of doing it) for an Object to be used as a lock:
Object lock = new Object();
....
synchronized(lock)
{
}
How is Object any more offensive than null?
It makes a good place marker (as good as null anyway).
Also, I don't think it would be good design to make an object abstract without an abstract method that needs to go on it.
I'm not saying null is the best thing since sliced bread--I read an article the other day by the "Inventor" discussing the cost/value of having the concept of null... (I didn't even think null was inventable! I guess someone somewhere could claim he invented zero..) just that being able to instantiate Object is no worse than being able to pass null.
You never know when you might want to use a simple Object as a placeholder. Think of it as like having a zero in a numerical system (and null doesn't work for this, since null represents the absence of data).
There should be a reason to make a class abstract. One is to prevent clients from instantiating the class and force them into using only subclasses (for whatever reasons). Another is if you wish to use it as an interface by providing abstract methods, which subclasses must implement. Probably, the designers og Java saw no such reasons, so java.lang.Object remains concrete.
As always, Guava comes to help: with http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Optional.html
Stuff here can be used to kill nulls / Object instances for "a not-null placeholder" from the code.
There are entirely seperated questions here:
why did not they make Object abstract?
how much disaster comes after if they decide to make it abstract in a future release?
I'll just throw in another reason that I've found Object to useful to instantiate on its own. I have a pool of objects I've created that has a number of slots. Those slots can contain any of a number of objects, all that inherit from an abstract class. But what do I put in the pool to represent "empty". I could use null, but for my purpose, it made more sense to insure that there was always some object in each slot. I can't instantiate the abstract class to put in there, and I wouldn't have wanted to. So I could have created a concrete subclass of my abstract class to represent "not a useful foo", but that seemed unnecessary when using an instance of Object was just as good..in fact better, as it clearly says that what's in the slot has no functionality. So when I initialize my pool, I do so by creating an Object to assign to each slot as the initial condition of the pool.
I agree that it might have made sense for the original Java crew to have defined a Placeholder object as a concrete subclass of Object, and then made Object abstract, but it doesn't rub me wrong at all that they went the way they did. I would then have used Placeholder in place of Object.

Categories

Resources