I know of at least 2 mechanisms to enforce that a Collection should not be modified:
Java's unmodifiable Collections: http://www.tutorialspoint.com/java/util/collections_unmodifiablelist.htm
Guava's immutable collections: http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ImmutableList.html
However, I notice both of them enforce the contract at runtime, by throwing exceptions (e.g UnsupportedOperationException).
Questions:
Are there existing libraries/language features that allow immutability checks to be performed at compile-time?
If not, why not? Is it because of a language limitation, the result of a design decision, or some other reason?
The original authors of the Collections APIs (unfortunately) did not make a distinction between immutable and mutable collections. An immutable API would have no mutating methods (but would likely rebuild collections internally as Persistent data structure).
See Scala as an example of a Collections API on the JVM that supports both immutable and mutable collections.
You could only do this by having no mutating methods on the class. But you're stuck if you want to implement an existing interface that has methods with mutating semantics (even static analysis won't help you in the general case).
Related
Is there any way to force an instance or a functional interface static method output to be inmutable in a fashion like Collections.immutable(x)?
I'd like for instance to create sort of Comparator functional interface and disallow chained operations like ".thenComparing()" for some of the static builder-like methods created instances.
You can force your return value to be immutable by returning an instance of an immutable class. There is no general purpose way to make instances of your class immutable without knowing what the class does.
The second paragraph of your question contains an incorrect assumption that .thenComparing(...) makes a comparator mutable. thenComparing leaves the original comparator intact and makes a new comparator.
Sadly, the Java collection types lack immutable collections, but google guava comes with lots of immutable collections (see https://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained), so you can use those as a return type.
Yet, I can't see how this correlates with the ability to compare something, since comparing doesn't change stuff.
I cannot fathom why Java wishes to hide immutable unmodifiable collections from being passed around.
It makes life harder on devs because you can't guarantee that a class is returning anything immutable unmodifiable, forcing you to smatter calls to Collections.unmodifiableWhatever throughout your code. This is both wasteful and annoying.
Is there a reason I'm missing behind why you would make these methods protected, or another library I'm missing that contains public versions of immutable and/or unmodifiable collections?
For the purposes of learning more about java, let's say Scala does not count as an answer to "a library that contains public versions of immutable collections" :)
I think it has to do with the design goals of the framework:
The main design goal was to produce an API that was small in size and, more importantly, in "conceptual weight."
(Source)
You should check out Guava's immutable collection types, if you are willing to learn more conceptual weight :)
The Collections interface permits one to wrap an exiting Collection so that calls to mutator methods result in failure.
unmodifiableCollection(Collection c): "Returns an unmodifiable view of the specified collection."
It makes life harder on devs because you can't guarantee that a class is returning anything immutable, ... This is both wasteful and annoying.
The JDK source of the Collections.unmodifiableList() method is:
public static <T> List<T> unmodifiableList(List<? extends T> list) {
return (list instanceof RandomAccess ?
new UnmodifiableRandomAccessList<>(list) :
new UnmodifiableList<>(list));
}
I see why this can be considered wasteful (these generics also make it ugly). Why doesn't that method check whether the passed instance is already an UnmodifiableRandomAccessList or UnmodifiableList?
We know that we should favor composition over inheritance, right? Well, the implementers of the
sort() template method decided not to use inheritance and instead to implement sort() as a static
method that is composed with a Comparable at runtime.
How is this better?
How is it worse?
How would you approach this problem?
Do Java arrays make this particularly tricky?
There are always design debates about adding functionality to a Class, or to an associated utility class. Like you, I prefer the former, but some argue that this can make a class "too big". I would put sort() in Collection, not in Collections, but Sun decided otherwise.
Also, an array is, in some ways, not treated as a "real" class, so there might have been implementation issues.
Clarification added
You would still want a static sort() utility method in Collections (or in AbstractCollection) so that the canned implementations, and any user-defined implementations, could easily sort themselves. So, MyGoofyCollection.sort() could just call Collections.sort(this); However, the idiom I would prefer for usage is to call myCollection.sort(), instead of the current Collections.sort(myCollection).
Note that this also allows a specific implementation to provide their own, optimized implementation of sort(). For example, if I have a AlwaysSortedList, it's implementation of sort() is to do nothing.
However, this is all fairly useless discussion, as Java has already implemented it their way and it's unlikely to change... Maybe in Java 9 or 10?
I am trying to apply the lessons from reading Java Concurrency In Practice with regards to declaring whether classes that I write are either thread-safe or that they contain unsynchronised mutable state. I think this is a good idea because it documents the intention of how the class should be used.
Today, I wrote a class which wraps an instance of java.lang.Class and java.net.URI. I was about to write in the javadoc that it is thread-safe immutable since both fields were declared as final references. However, I looked at the source code for URI and Class and didn't see any declaration of whether they are thread-safe and it didn't seem immediately obvious.
Thinking about this more generally: is there a list of common java classes stating whether they are thread-safe or not?
On the other had, it probably doesn't matter whether the instances are strictly thread-safe because of the way this class is being used, I will mark it as 'probably thread-safe' for now.
There is no definitive list of thread-safe classes in Java. The only people who could produce a definitive list would be Oracle1, and they haven't done so.
1 - Oracle is the custodian of both the reference Java class libraries (including javadocs), other "official" documentation and .. the official compliance test suite for Java. They are the people who would say whether a class (or subset of a class) that is thread-safe, is thread-safe by design, or whether it is merely a implementation artefact. Nobody else can make that calll with total certainty; i.e. whether a class that is thread-safe in the standard Oracle codebase should also be thread-safe in Harvest / Android codebase or the Classpath codebase, or ...
All immutable classes are assumed to be thread-safe. For mutable classes the common practice is to state explicitly when the class is thread-safe; if nothing is stated, you can't assume thread safety.
I have never heard of a list of thread-safe JDK classes, though.
All java.lang classes (As Marko said immutable classes are assumed to be thread-safe). Also BigDecimal and BigInteger and few more. Unfortunately there is no list of that classes.
If you need some thread-safe collections try Google Guava Immutable Collections (http://code.google.com/p/guava-libraries/wiki/GuavaExplained?tm=6)
Generally speaking, the more I use immutable objects in Java the more I'm thinking they're a great idea. They've got lots of advantages from automatically being thread-safe to not needing to worry about cloning or copy constructors.
This has got me thinking, would an "immutable" keyword go amiss? Obviously there's the disadvantages with adding another reserved word to the language, and I doubt it will actually happen primarily for the above reason - but ignoring that I can't really see many disadvantages.
At present great care has to be taken to make sure objects are immutable, and even then a dodgy javadoc comment claiming a component object is immutable when it's in fact not can wreck the whole thing. There's also the argument that even basic objects like string aren't truly immutable because they're easily vunerable to reflection attacks.
If we had an immutable keyword the compiler could surely recursively check and give an iron clad guarantee that all instances of a class were immutable, something that can't presently be done. Especially with concurrency becoming more and more used, I personally think it'd be good to add a keyword to this effect. But are there any disadvantages or implementation details I'm missing that makes this a bad idea?
In general, immutable objects should be preferred over stateful objects, and it's currently fairly difficult to make an immutable object in Java. In fact, most OO languages have poor support for immutable objects, while most functional languages take them for granted, such as F#, Haskell, and Clojure.
Adding an immutable keyword to Java could make code...
Easier to write. No messing with final and private, no accidentally adding a method that makes the class mutable, and possibly no manually marking the class final (subclasses can add mutable state).
Easier to read. You don't need to say that the class is immutable in English, you can say it in the code itself. An immutable keyword is a good step toward self-documenting code.
Faster (theoretically). The more the compiler knows about your code, the more optimizations it can make. Without this keyword, every call to new ImmutableFoo(1, 2, 3) must create a new object, unless the compiler can prove that your class can't be mutated. If ImmutableFoo was marked with the immutable keyword, every such call could return the same object. I'm pretty sure new must always create a new object, which makes this point invalid, but effective communication with the compiler is still a good thing.
Scala's case classes are similar to an immutable keyword. An immutable keyword was also being considered in C# 5.
While making all fields final and also verifying any class references are also immutable is possible there are other situations where this becomes impossible.
What if your final class also includes some lazy loaded fields ?
One would need further support for marking such fields as immutable and lazy.
Taking a look at java.lang.String with its array of chars[] how could the compiler really know for sure that it is immutable ? Everybody knows string is but another similar class could very easily include a method which updates an array. Further support would need to verify that once the field was set, no other instruction could "write" to the array. Before long this becomes a very complex problem.
In the end any such keyword if it did work might help, but it still does not mean programs are any better. Good design by good coders means better results. Dumb coders can still write crap even if the platform limits some pitfalls.
I'm a big fan of immutability, so in my opinion, absolutely. The advantages of immutability in OO programming are innumerable, and it shouldn't be the domain of just functional programming languages.
IMHO, object-oriented frameworks (Java, .net, etc.) should include more array types: mutable array, immutable array, mutable array references, immutable array references, and read-only array references (a read-only reference could point to either a mutable or immutable array, but in neither case would allow writing). Without an immutable array type, it's hard to construct many efficient types in a way that can be proven to be immutable.