In my code, I am creating a collection of objects which will be accessed by various threads in a fashion that is only safe if the objects are immutable. When an attempt is made to insert a new object into my collection, I want to test to see if it is immutable (if not, I'll throw an exception).
One thing I can do is to check a few well-known immutable types:
private static final Set<Class> knownImmutables = new HashSet<Class>(Arrays.asList(
String.class, Byte.class, Short.class, Integer.class, Long.class,
Float.class, Double.class, Boolean.class, BigInteger.class, BigDecimal.class
));
...
public static boolean isImmutable(Object o) {
return knownImmutables.contains(o.getClass());
}
This actually gets me 90% of the way, but sometimes my users will want to create simple immutable types of their own:
public class ImmutableRectangle {
private final int width;
private final int height;
public ImmutableRectangle(int width, int height) {
this.width = width;
this.height = height;
}
public int getWidth() { return width; }
public int getHeight() { return height; }
}
Is there some way (perhaps using reflection) that I could reliably detect whether a class is immutable? False positives (thinking it's immutable when it isn't) are not acceptable but false negatives (thinking it's mutable when it isn't) are.
Edited to add: Thanks for the insightful and helpful answers. As some of the answers pointed out, I neglected to define my security objectives. The threat here is clueless developers -- this is a piece of framework code that will be used by large numbers of people who know next-to-nothing about threading and won't be reading the documentation. I do NOT need to defend against malicious developers -- anyone clever enough to mutate a String or perform other shenanigans will also be smart enough to know it's not safe in this case. Static analysis of the codebase IS an option, so long as it is automated, but code reviews cannot be counted on because there is no guarantee every review will have threading-savvy reviewers.
There is no reliable way to detect if a class is immutable. This is because there are so many ways a property of a class might be altered and you can't detect all of them via reflection.
The only way to get close to this is:
Only allow final properties of types that are immutable (primitive types and classes you know are immutable),
Require the class to be final itself
Require that they inherit from a base class you provide (which is guaranteed to be immutable)
Then you can check with the following code if the object you have is immutable:
static boolean isImmutable(Object obj) {
Class<?> objClass = obj.getClass();
// Class of the object must be a direct child class of the required class
Class<?> superClass = objClass.getSuperclass();
if (!Immutable.class.equals(superClass)) {
return false;
}
// Class must be final
if (!Modifier.isFinal(objClass.getModifiers())) {
return false;
}
// Check all fields defined in the class for type and if they are final
Field[] objFields = objClass.getDeclaredFields();
for (int i = 0; i < objFields.length; i++) {
if (!Modifier.isFinal(objFields[i].getModifiers())
|| !isValidFieldType(objFields[i].getType())) {
return false;
}
}
// Lets hope we didn't forget something
return true;
}
static boolean isValidFieldType(Class<?> type) {
// Check for all allowed property types...
return type.isPrimitive() || String.class.equals(type);
}
Update: As suggested in the comments, it could be extended to recurse on the superclass instead of checking for a certain class. It was also suggested to recursively use isImmutable in the isValidFieldType Method. This could probably work and I have also done some testing. But this is not trivial. You can't just check all field types with a call to isImmutable, because String already fails this test (its field hash is not final!). Also you are easily running into endless recursions, causing StackOverflowErrors ;) Other problems might be caused by generics, where you also have to check their types for immutablity.
I think with some work, these potential problems might be solved somehow. But then, you have to ask yourself first if it really is worth it (also performance wise).
Use the Immutable annotation from Java Concurrency in Practice. The tool FindBugs can then help in detecting classes which are mutable but shouldn't be.
At my company we've defined an Attribute called #Immutable. If you choose to attach that to a class, it means you promise you're immutable.
It works for documentation, and in your case it would work as a filter.
Of course you're still depending on the author keeping his word about being immutable, but since the author explicitly added the annotation it's a reasonable assumption.
Basically no.
You could build a giant white-list of accepted classes but I think the less crazy way would be to just write in the documentation for the collection that everything that goes is this collection must be immutable.
Edit: Other people have suggested having an immutable annotation. This is fine, but you need the documentation as well. Otherwise people will just think "if I put this annotation on my class I can store it in the collection" and will just chuck it on anything, immutable and mutable classes alike. In fact, I would be wary of having an immutable annotation just in case people think that annotation makes their class immutable.
In my code, I am creating a collection of objects which will be accessed by various threads in a fashion that is only safe if the objects are immutable.
Not a direct answer to your question, but keep in mind that objects that are immutable are not automatically guaranteed to be thread safe (sadly). Code needs to be side-effect free to be thread safe, and that's quite a bit more difficult.
Suppose you have this class:
class Foo {
final String x;
final Integer y;
...
public bar() {
Singleton.getInstance().foolAround();
}
}
Then the foolAround() method might include some non-thread safe operations, which will blow up your app. And it's not possible to test for this using reflection, as the actual reference can only be found in the method body, not in the fields or exposed interface.
Other than that, the others are correct: you can scan for all declared fields of the class, check if every one of them is final and also an immutable class, and you're done. I don't think methods being final is a requirement.
Also, be careful about recursively checking dependent fields for immutability, you might end up with circles:
class A {
final B b; // might be immutable...
}
class B {
final A a; // same so here.
}
Classes A and B are perfectly immutable (and possibly even usable through some reflection hacks), but naive recursive code will go into an endless loop checking A, then B, then A again, onwards to B, ...
You can fix that with a 'seen' map that disallows cycles, or with some really clever code that decides classes are immutable if all their dependees are immutable only depending on themselves, but that's going to be really complicated...
This could be another hint:
If the class has no setters then it cannot be mutated, granted the parameters it was created with are either "primitive" types or not mutable themselves.
Also no methods could be overridden, all fields are final and private,
I'll try to code something tomorrow for you, but Simon's code using reflection looks pretty good.
In the mean time try to grab a copy of the "Effective Java" book by Josh Block, it has an Item related to this topic. While is does not for sure say how to detect an immutable class, it shows how to create a good one.
The item is called: "Favor immutability"
Updated link: https://www.amazon.com/Effective-Java-Joshua-Bloch/dp/0134685997
You Can Ask your clients to add metadata (annotations) and check them at runtime with reflection, like this:
Metadata:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.CLASS)
public #interface Immutable{ }
Client Code:
#Immutable
public class ImmutableRectangle {
private final int width;
private final int height;
public ImmutableRectangle(int width, int height) {
this.width = width;
this.height = height;
}
public int getWidth() { return width; }
public int getHeight() { return height; }
}
Then by using reflection on the class, check if it has the annotation (I would paste the code but its boilerplate and can be found easily online)
why do all the recommendations require the class to be final? if you are using reflection to check the class of each object, and you can determine programmatically that that class is immutable (immutable, final fields), then you don't need to require that the class itself is final.
You can use AOP and #Immutable annotation from jcabi-aspects:
#Immutable
public class Foo {
private String data;
}
// this line will throw a runtime exception since class Foo
// is actually mutable, despite the annotation
Object object = new Foo();
Like the other answerers already said, IMHO there is no reliable way to find out if an object is really immutable.
I would just introduce an interface "Immutable" to check against when appending. This works as a hint that only immutable objects should be inserted for whatever reason you're doing it.
interface Immutable {}
class MyImmutable implements Immutable{...}
public void add(Object o) {
if (!(o instanceof Immutable) && !checkIsImmutableBasePrimitive(o))
throw new IllegalArgumentException("o is not immutable!");
...
}
Try this:
public static boolean isImmutable(Object object){
if (object instanceof Number) { // Numbers are immutable
if (object instanceof AtomicInteger) {
// AtomicIntegers are mutable
} else if (object instanceof AtomicLong) {
// AtomLongs are mutable
} else {
return true;
}
} else if (object instanceof String) { // Strings are immutable
return true;
} else if (object instanceof Character) { // Characters are immutable
return true;
} else if (object instanceof Class) { // Classes are immutable
return true;
}
Class<?> objClass = object.getClass();
// Class must be final
if (!Modifier.isFinal(objClass.getModifiers())) {
return false;
}
// Check all fields defined in the class for type and if they are final
Field[] objFields = objClass.getDeclaredFields();
for (int i = 0; i < objFields.length; i++) {
if (!Modifier.isFinal(objFields[i].getModifiers())
|| !isImmutable(objFields[i].getType())) {
return false;
}
}
// Lets hope we didn't forget something
return true;
}
To my knowledge, there is no way to identify immutable objects that is 100% correct. However, I have written a library to get you closer. It performs analysis of bytecode of a class to determine if it is immutable or not, and can execute at runtime. It is on the strict side, so it also allows whitelisting known immutable classes.
You can check it out at: www.mutabilitydetector.org
It allows you to write code like this in your application:
/*
* Request an analysis of the runtime class, to discover if this
* instance will be immutable or not.
*/
AnalysisResult result = analysisSession.resultFor(dottedClassName);
if (result.isImmutable.equals(IMMUTABLE)) {
/*
* rest safe in the knowledge the class is
* immutable, share across threads with joyful abandon
*/
} else if (result.isImmutable.equals(NOT_IMMUTABLE)) {
/*
* be careful here: make defensive copies,
* don't publish the reference,
* read Java Concurrency In Practice right away!
*/
}
It is free and open source under the Apache 2.0 license.
Something which works for a high percentage of builtin classes is test for instanceof Comparable. For the classes which are not immutable like Date, they are often treated as immutable in most cases.
I appreciate and admire the amount of work Grundlefleck has put into his mutability detector, but I think it is a bit of an overkill. You can write a simple but practically very adequate (that is, pragmatic) detector as follows:
(note: this is a copy of my comment here: https://stackoverflow.com/a/28111150/773113)
First of all, you are not going to be just writing a method which determines whether a class is immutable; instead, you will need to write an immutability detector class, because it is going to have to maintain some state. The state of the detector will be the detected immutability of all classes which it has examined so far. This is not only useful for performance, but it is actually necessary because a class may contain a circular reference, which would cause a simplistic immutability detector to fall into infinite recursion.
The immutability of a class has four possible values: Unknown, Mutable, Immutable, and Calculating. You will probably want to have a map which associates each class that you have encountered so far to an immutability value. Of course, Unknown does not actually need to be implemented, since it will be the implied state of any class which is not yet in the map.
So, when you begin examining a class, you associate it with a Calculating value in the map, and when you are done, you replace Calculating with either Immutable or Mutable.
For each class, you only need to check the field members, not the code. The idea of checking bytecode is rather misguided.
First of all, you should not check whether a class is final; The finality of a class does not affect its immutability. Instead, a method which expects an immutable parameter should first of all invoke the immutability detector to assert the immutability of the class of the actual object that was passed. This test can be omitted if the type of the parameter is a final class, so finality is good for performance, but strictly speaking not necessary. Also, as you will see further down, a field whose type is of a non-final class will cause the declaring class to be considered as mutable, but still, that's a problem of the declaring class, not the problem of the non-final immutable member class. It is perfectly fine to have a tall hierarchy of immutable classes, in which all the non-leaf nodes must of course be non-final.
You should not check whether a field is private; it is perfectly fine for a class to have a public field, and the visibility of the field does not affect the immutability of the declaring class in any way, shape, or form. You only need to check whether the field is final and its type is immutable.
When examining a class, what you want to do first of all is to recurse to determine the immutability of its super class. If the super is mutable, then the descendant is by definition mutable too.
Then, you only need to check the declared fields of the class, not all fields.
If a field is non-final, then your class is mutable.
If a field is final, but the type of the field is mutable, then your class is mutable. (Arrays are by definition mutable.)
If a field is final, and the type of the field is Calculating, then ignore it and proceed to the next field. If all fields are either immutable or Calculating, then your class is immutable.
If the type of the field is an interface, or an abstract class, or a non-final class, then it is to be considered as mutable, since you have absolutely no control over what the actual implementation may do. This might seem like an insurmountable problem, because it means that wrapping a modifiable collection inside an UnmodifiableCollection will still fail the immutability test, but it is actually fine, and it can be handled with the following workaround.
Some classes may contain non-final fields and still be effectively immutable. An example of this is the String class. Other classes which fall into this category are classes which contain non-final members purely for performance monitoring purposes (invocation counters, etc.), classes which implement popsicle immutability (look it up), and classes which contain members that are interfaces which are known to not cause any side effects. Also, if a class contains bona fide mutable fields but promises not to take them into account when computing hashCode() and equals(), then the class is of course unsafe when it comes to multi-threading, but it can still be considered as immutable for the purpose of using it as a key in a map. So, all these cases can be handled in one of two ways:
Manually adding classes (and interfaces) to your immutability detector. If you know that a certain class is effectively immutable despite the fact that the immutability test for it fails, you can manually add an entry to your detector which associates it with Immutable. This way, the detector will never attempt to check whether it is immutable, it will always just say 'yes, it is.'
Introducing an #ImmutabilityOverride annotation. Your immutability detector can check for the presence of this annotation on a field, and if present, it may treat the field as immutable despite the fact that the field may be non-final or its type may be mutable. The detector may also check for the presence of this annotation on the class, thus treating the class as immutable without even bothering to check its fields.
I hope this helps future generations.
Related
Whenever I think that I am gaining some confidence in OOP then suddenly I get bitten by some advance example. Like in this very great article by Uncle Bob he uses the below class an example for his kata.
public class WordWrapper {
private int length;
public WordWrapper(int length) {
this.length = length;
}
public static String wrap(String s, int length) {
return new WordWrapper(length).wrap(s);
}
public String wrap(String s) {
if (length < 1)
throw new InvalidArgument();
if (s == null)
return "";
if (s.length() <= length)
return s;
else {
int space = s.indexOf(" ");
if (space >= 0)
return breakBetween(s, space, space + 1);
else
return breakBetween(s, length, length);
}
}
private String breakBetween(String s, int start, int end) {
return s.substring(0, start) +
"\n" +
wrap(s.substring(end), length);
}
public static class InvalidArgument extends RuntimeException {
}
}
I have following doubts:
Why the static helper method wrap?
Why the InvalidArgument class is nested and static?
Why do we even need to initialize this class since its nothing but an algorithm and can operate without any instance variable, why we need ~100 instances(for eg) of it?
Why the static helper method wrap?
There is no especially good reason - I think that it is a subjective judgement that:
WordWrapper.wrap("foo", 5);
is neater than
new WordWrapper(5).wrap("foo");
(which I would agree it is). I tend to find myself adding methods like this when the code just feels very repetitive.
However, the static form can lead to hidden problems: invoking that in a loop results in the creation of a lot of unnecessary instances of WordWrapper, whereas the non-static form just creates one and reuses it.
Why the InvalidArgument class is nested and static?
The implication of it being nested is that it is only for use in reporting invalid arguments of methods in WordWrapper. For instance, it wouldn't make much sense if some database-related class threw an instance of WordWrapper.InvalidArgument.
Remember that you can reference it as InvalidArgument for convenience if appropriately imported; you're still always using some.packagename.WordWrapper.InvalidArgument, so its use in other classes doesn't make semantic sense.
If you expect to use it in other classes, it should not be nested.
As for why static: there are two reasons that I can think of (which are sort of different sides of the same coin):
It doesn't need to be non-static. A non-static nested class is called an inner class. It is related to the instance of the containing class which created it; in some way, the data in the inner class is related to the data in the outer class.
What this actually means is there is a hidden reference to the outer class passed into the inner class when it is created. If you never need to refer to this instance, make it static, so the reference isn't passed. It's just like removing unused parameters of methods: if you don't need it, don't pass it.
Holding this reference has unexpected consequences. (I draw this as a separate point because whereas the previous one refers to a logical requirement/design for the reference or not, this refers to practical implications of holding that reference).
Just as with holding any reference, if you have a reference to an instance of the inner class, you make everything that it references ineligible for garbage collection, since it is still reachable. Depending upon how you use instances of the inner class, this can lead to a memory leak. The static version of the class doesn't suffer from this problem, since there is no reference: you can have a reference to a InvalidArgument when all of the instances of Wrapper are cleared up.
Another consequence is that the contract of InvalidArgument is invalid: Throwable, a superclass of InvalidArgument, implements Serializable, meaning that InvalidArgument also implements Serializable. However, WordWrapper is not Serializable. As such, serialization of a non-static InvalidArgument would fail because of the non-null reference to WordWrapper.
The simple solution to both of these issues is to make the nested class static; as a defensive strategy, one should make all nested classes static, unless you really need them not to be.
Why do we even need to initialize this class since its nothing but an algorithm...
Good question. This is sort of related to your first question: you could get away with just the static helper method, and remove the instance methods and state.
Before you chuck away your instance methods, there are advantages to instance methods over static methods.
The obvious one is that you are able to store state in the instances, for instance length. This allows you to pass fewer parameters to wrap, which might make the code less repetitive; I suppose it gives an effect a bit like partial evaluation. (You can store state in static variables too, but global mutable state is a royal PITA; that's another story).
Static methods are a tight coupling: the class using WordWrapper is tightly bound to a specific implementation of word wrapping.
For many purposes, one implementation might be fine. However, there is almost always a case for at least two implementations (your production and test implementations).
So, whereas the following is tightly bound to one implementation:
void doStuffWithAString(String s) {
// Do something....
WordWrapper.wrap(s, 100);
// Do something else ....
}
the following can have an implementation provided at runtime:
void doStuffWithAString(WordWrapper wrapper, String s) {
// Do something....
wrapper.wrap(s);
// Do something else ....
}
which is using the wrapper as a strategy.
Now, you can select the word wrapping algorithm used for a particular case (e.g. one algorithm works well for English, but another works better for Chinese - maybe, I don't know, it's just an example).
Or, for a test, you can inject a mocked instance for tests which just returns the parameter - this allows you to test doStuffWithAString without testing the implementation of WordWrapper at the same time.
But, with flexibility comes overhead. The static method is more concise. For very simple methods, static could well be the way to go; as the method gets more complicated (and, particularly in the testing case, it becomes harder and harder to work out the input to provide to get a specific output which is important to your test case), the instance method form becomes a better choice.
Ultimately, there is no hard-and-fast rule for which to use. Be aware of both, and notice which works best in given situations.
If I have a class like that:
public class MyObject {
private int myField = 2;
public void setMyField(int f) {
this.myField = f;
}
}
Will objects of this class be mutable?
Thanks!
Of course - if you want it to be immutable, then you need something like:
public class MyObject {
private final int myField;
public MyObject(int f) {
myfield = f;
}
public int getMyField() {
return myField;
}
}
yes
Mutable objects have fields that can be changed, immutable objects
have no fields that can be changed after the object is created.
You already have several answers with a "Yes".
I would like to add a "but" (if I would be bold, I would say "No" ;-)
Yes, an object of this class appears to be mutable, since it provides a setter to change the field. However, since it does not have a getter for that field, neither any other getter depending on that field, and since the field is private, it is currently not possible to read that state.
Put differently: The object has state, but it does not expose any state to the outside.
I would call that object "effectively immutable".
There are some design patterns, where objects are "effectively immutable", for example "Lazy Initialization" of an "Immutable Object".
Note: The concept of being "effectively immutable" is discussed in Section 3.5.4 of Java Concurrency in Practice by Brian Goetz.
Yes, objects of this class are mutable. The designer of the class can't prohibit by any technical means (in real existing Java) consumers of the objects to observe and modify the contents of the field.
private is an explicitly declared contract regarding intended usage of the field - this contract can be broken, e.g. with reflection.
Not providing any methods that change the data of an object after creation can also be a (implicitly declared) contract about intended use and mutability - this contract, too, can be broken, like any contract that needs two conforming parties.
Edit: Unless there is another party that has the means to enforce - like in Java the SecurityManager stopping you from changing a final field at runtime.
Yes, your object is mutable as the value of myField can be changed after the instance is created using the setter.
Immutability can be achieved using final fields, as it will not allow you to change the value of a variable once it is initialized.
Answer by #JakubK points out how you can make your class Immutable.
But declaring reference final wont make the object being pointed by it final.
For example:
class MyObject{
private final List<Integer> list = new ArrayList<Integer>();
public List<Integer> getList(){
return list;
}
}
I can change add a new element to the list from outside by doing something like this
instance.getList().add(1); //mutates the list
This example is not immutable, as the List can be changed by someone else.
To define whether something is mutable, one has to define what state is encapsulated thereby. If MyObject specifies that its state includes the value which Reflection will report for myField, then it is mutable. If that field is not specified as being part of the object's observable state, then it may be most purposes regarded as immutable.
To be more specific, I would regard a class as being immutable only if one could perform any combination of documented operations upon the class, in any sequence and with any timing (even on multiple threads), and not have any documented behavioral aspects of of any of them affected by any other. The fact that a method might change the contents of a private field is relevant if and only if that change would affect some documented behavioral aspect of another method call (to the same or different method). For example, I would say that the fact that String.hashCode() modifies the hash field does not make String mutable, because the value returned by hashCode() is not affected by whether or not the field had been written previously. If a class had a hashCode method which would, if a field was blank, generate a random number and store it in that field, and otherwise return the value directly, such a class would be mutable unless it ensured that the field was tested and set as an atomic operation. In the absence of such assurance, it would be possible for near-simultaneous calls to hashCode() to yield different values, and thus for future calls to differ values that would differ from at least one of them (implying that the object's state had changed between the call that returned the odd-ball value and the later call).
I wish to alert the developer when he attempts to mutate an immutable object. The immutable object is actually an extension of a mutable object, and overrides the setters on said object to make it immutable.
Mutable base class: Vector3
public class Vector3 {
public static final Vector3 Zero = new ImmutableVector3(0, 0, 0);
private float x;
private float y;
private float z;
public Vector3(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
public void set(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
}
}
Immutable version: ImmutableVector3
public final class ImmutableVector3 extends Vector3 {
public ImmutableVector3(float x, float y, float z) {
super(x, y, z);
}
//Made immutable by overriding any set functionality.
#Override
public void set(float x, float y, float z) {
throw new Exception("Immutable object."); //Should I even throw an exception?
}
}
My use case is as follows:
public class MyObject {
//position is set to a flyweight instance of a zero filled vector.
//Since this is shared and static, I don't want it mutable.
private Vector3 position = Vector3.Zero;
}
Let's say that a developer on my team decides he needs to manipulate the position of the object, but currently it's set to the static, immutable Vector3.Zero shared vector instance.
It would be best if he knew ahead of time that he needs to create a new instance of a mutable vector if the position vector is set to the shared instance of Vector3.Zero:
if (position == Vector3.Zero)
position = new Vector3(x, y, z);
But, let's say he doesn't check this first. I think, in this case, it would be good to throw an Exception as shown above in the ImmutableVector3.set(x,y,z) method. I wanted to use a standard Java exception, but I wasn't sure which would be most fitting, and I'm not 100% convinced this is the best way to handle this.
The suggestions I've seen on (this question)[Is IllegalStateException appropriate for an immutable object? seem to suggest the following:
IllegalStateException - but it's an immutable object, thus only has a single state
UnsupportedOperationException - the set() method is unsupported since it overrides the base class, so this might be a good choice.
NoSuchElementException - I'm not sure how this would be a good choice unless the method is considered an element.
Furthermore, I'm not even sure I should throw an exception here. I could simply not change the object, and not alert the developer that they are trying to change an immutable object, but that seems troublesome as well. The problem with throwing an exception in ImmutableVector3.set(x,y,z) is that set has to throw an Exception on both ImmutableVector3 and Vector3. So now, even though Vector3.set(x,y,z) will never throw an exception, it has to be placed in a try/catch block.
Questions
Am I overlooking another option besides throwing exceptions?
If exceptions are the best way to go, which exception should I choose?
Throwing an exception is usually the way to go, and you should use UnsupportedOperationException.
The Java API itself does recommend this in the collections framework:
The "destructive" methods contained in this interface, that is, the methods that modify the collection on which they operate, are specified to throw UnsupportedOperationException if this collection does not support the operation.
An alternative if you create the full class hierarchy is to create a super class Vector that is not modifiable and has no modifying methods like set(), and two sub-classes ImmutableVector (that guarantees immutability) and MutableVector (that is modifiable). This would be better because you get compile-time safety (you can't even try to modify an ImmutableVector), but depending on the situation might be over-engineered (and you might end up with many classes).
This approach was for example chosen for the Scala collections, they all exist in three variations.
In all cases where you want to modify the vector, you use the type MutableVector. In all cases where you don't care about modifying and just want to read from it, you just use Vector. In all cases where you want to guarantee immutability (e.g., a Vector instance is passed into a constructor and you want to ensure that nobody will modify it later) you use ImmutableVector (which would usually provide a copy method, so you just call ImmutableVector.copyOf(vector)). Down-casting from Vector should never be necessary, specify the correct sub-type that you need as type instead. The whole point of this solution (which needs more code) is about being type safe and with compile-time checks, so down-casting destroy that benefit. There are exceptions, though, for example the ImmutableVector.copyOf() method would, as an optimization, usually look like this:
public static ImmutableVector copyOf(Vector v) {
if (v instanceof ImmutableVector) {
return (ImmutableVector)v;
} else {
return new ImmutableVector(v);
}
}
This is still safe and gives you one further benefit of immutable types, namely the avoidance of unnecessary copying.
The Guava library has a large collection of immutable collection implementations that follow these pattern (although they still extend the mutable standard Java collection interfaces and thus provide no compile-time safety). You should read the description of them to learn more about immutable types.
The third alternative would be to just have on immutable vector class, and no mutable classes at all. Very often mutable classes used for performance reasons are a premature optimization, as Java is very good in handling lots of small short-lived temporary objects (due to a generational garbage collector, object allocation is extremely cheap, and object cleanup can even be without any cost in the best case). Of course this is no solution for very large objects like lists, but for a 3-dimensional vector this is surely an option (and probably the best combination because its easy, safe, and needs less code than the others). I do not know any examples in the Java API of this alternative, because back in the days when most parts of the API were created, the VM was not that optimized and so too many objects were maybe a performance problem. But that should not prevent you from doing so today.
You should throw a compiler error if you try to mutate an immutable class.
Immutable classes should not extend mutable ones.
Given your situation, I think you should throw an UnsupportedOperationException. Here's why:
package com.sandbox;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Sandbox {
public static void main(String[] args) throws IOException {
List<Object> objects = Collections.unmodifiableList(new ArrayList<Object>());
objects.add(new Object());
}
}
This will throw a UnsupportedOperationException and is a very similar situation to yours.
But an even better thing to do (which may not be possible) is to design your immutable classes so there isn't a mutating method to call in the first place. As a developer, I don't want to learn at runtime that I can't use a method, I want to learn at or before compile time.
Your set method should return a new ImmutableVector which doesn't mutate anything.
You might want to take #SotiriosDelimanolis's idea, and make both classes implement an interface without a setter and then have your code pass around the interface. Again, this may not be possible given your legacy code.
Immutable classes should not derive from concrete mutable classes, nor vice versa. Instead, you should have a ReadableFoo abstract class with concrete MutableFoo and ImmutableFoo derivatives. That way a method which wants an object it can mutate can demand MutableFoo, a method which wants an object whose present state can be persisted merely by persisting a reference to the object can demand ImmutableFoo, and a method which won't want to change an object state and won't care what the state does after it returns can freely accept ReadableFoo without having to worry about whether they're mutable or immutable.
The trickiest aspect is deciding whether it's better to have the base class include a method to check whether it's mutable along with a "set" method which will throw if it isn't, or have it simply omit the "set" method. I would favor omitting the "set" method, unless the type includes features to facilitate a copy-on-write pattern.
Such a pattern may be facilitated by having the base class include abstract methods AsImmutable, AsMutable, along with concrete AsNewMutable. A method which is given a ReadableFoo named George and wants to capture its present state can store to a field GeorgeField either George.AsImmutable() or George.AsNewMutable() depending upon whether it thinks it will want to modify it. If it does need to modify it, it can set GeorgeField = GeorgeField.AsMutable(). If it needs to share it, it can return GeorgeField.AsImmutable(); if it expects to share it many times before changing it again, it can set GeorgeField = GeorgeField.AsImmutable(). If many objects need to share the states ...Foos, and most of them don't need to modify them at all but some need to modify them a lot, such an approach may work out more efficiently than using mutable or immutable objects alone.
I have an immutable object that doesn't have its fields or class marked as final. I could do this, but is there really any benefit to doing this? I could see it saving the compiler a little bit of time figuring things out, but I can't see it being "worth" it (other then the fact that it will make future developers rethink doing something to the object to make it mutable).
Apart from the points you make (future developer modifying the fields being a very sensible one, another one is that someone could subclass your class and make it mutable), explicitly marking the fields as final provides you with visibility guarantees in a multi threaded environment.
Take this class - it is effectively immutable:
public class SomeClass {
private int i;
public SomeClass(int i) { this.i = i; }
public int getI() { return this.i; }
}
In a multi-threaded environment, it is possible that a thread T1 creates a SomeClass sc = new SomeClass(1); and that another thread T2 reads sc.getI() and sees 0.
If i is made final, this can not happen any more (assuming you don't let this escape during construction, as explained in the quote below).
Reference: JLS #17.5 - emphasis mine
final fields also allow programmers to implement thread-safe immutable objects without synchronization. [...]
The usage model for final fields is a simple one: Set the final fields for an object in that object's constructor; and do not write a reference to the object being constructed in a place where another thread can see it before the object's constructor is finished. If this is followed, then when the object is seen by another thread, that thread will always see the correctly constructed version of that object's final fields.
It serves to show your intentions and not for someone to make it mutable by mistake.
Addionally marking a method as final may become inline gaining performance advantage.
Also marking the reference objects of a class as final forces the constructor to be atomic.
Finally marking the class as final stops inheritence. Is this what you need?
Making the field final is more about showing the intention of the code.
Unless you make the getter methods final, your class isn't immutable. Consider:
public class MyClass {
private final int num;
public int getNum() {
return num;
}
}
public class MySubClass extends MyClass {
private int num;
public int getNum() {
return num;
}
public void setNum(int i) {
num = i;
}
}
The subclass has completely overridden the field, making it mutable. All you have to do is cast an instance of MyClass to MySubClass to get access to the setter. Even without the setter, the subclass could change its num field in another method.
Assuming the field is private, it doesn't matter if the field is final: You need to either make your class final, or make your getter final.
Note also that even with all the code protection you like, using reflection other classes can still cut through everything and mutate your field.
First, a final field is something very different from a final class. A final field cannot be changed. The final modifier on classes means that no other class is allowed to inherit from that class, but has no implications for the fields at all.
That being said, having fields marked final does indeed allow the compiler to do some optimizations. How big the effect of those are depends a lot. If you have no performance issues in your program, it's probably not worth it.
But in terms of design, marking things final if they are intended to be final is useful so nobody who's using your class can inadvertently break something. So overall, if you have something that you by design don't want to change later on, make it final.
Is the below class immutable:
final class MyClass {
private final int[] array;
public MyClass(int[] array){
this.array = array;
}
}
No it is not because the elements of the array can still be changed.
int[] v1 = new int[10];
MyClass v2 = new MyClass(v1);
v1[0] = 42; // mutation visible to MyClass1
My two cents regarding immutability rules (which I retained from reading Effective Java - a great book!):
Don't provide methods that can modify the state of an object.
Make all your fields final.
Make sure that your class is non-extendable.
Make all your fields private.
Provide exclusive access to any fields or components of your class that can be changed. Essentially this applies to your situation (as explained by JaredPar). A person that uses your class still has a reference to your array. The opposite is the case where you return a reference to an component of your class. In this case, always create defensive copies. In your case, you should not assign the reference. Instead, copy the array that the user of your class provides, into your internal component.
"Immutability" is a convention between the programmer and himself. That convention may be more or less enforced by the compiler.
Instances of a class are "immutable" if they do not change during the normal course of the application code execution. In some cases we know that they do not change because the code actually forbids it; in other cases, this is just part of how we use the class. For instance, a java.util.Date instance is formally mutable (there is a setTime() method on it) but it is customary to handle it as if it were immutable; this is just an application-wide convention that the Date.setTime() method shall not be called.
As additional notes:
Immutability is often thought of in terms of "external characteristics". For instance, Java's String is documented to be immutable (that's what the Javadoc says). But if you look at the source code, you will see that a String instance contains a private field called hash which may change over time: this is a cache for the value returned by hashCode(). We still say that String is immutable because the hash field is an internal optimization which has no effect visible from the outside.
With reflection, the most private of instance fields can be modified (including those marked as final), if the programmer wishes so hard enough. Not that it is a good idea: it may break assumptions used by other pieces of code using the said instance. As I said, immutability is a convention: if the programmer wants to fight himself, then he can, but this can have adverse side-effects on productivity...
Most Java values are actually references. It is up to you to define whether a referenced object is part of what you consider to be "the instance contents". In your class, you have a field which references an (externally provided) array of integers. If the contents of that array are modified afterwards, would you consider that this breaks immutability of your MyClass instance ? There is no generic answer to that question.
There is no way to make an array immutable. That is there is no way to keep any client code from setting or removing or adding items to the array.
Here is a truly immutable alternative:
private static class MyClass
{
private List<Integer> list;
private MyClass(final int[] array)
{
final List<Integer> tmplist = new ArrayList<Integer>(array.length);
for (int i : array)
{
tmplist.add(array[i]);
}
this.list = Collections.unmodifiableList(tmplist);
}
}
To make a class immutable, you need to both ensure that all the fields on it are final, and that the types of those fields are immutable too.
This can be a pain to remember, but there is a tool to help you.
Pure4J provides an annotation #ImmutableValue, which you can add to an interface or class.
There is a maven plugin to check at compile-time that you are meeting the rules on immutability following this.
Hope this helps.