So question is: Is it possible to do Object Oriented Programming in java?
This presentation gave some insights into issue.
Jumping into conclusion fast: yes, it’s possible if being careful, and always using interfaces.
This part ”always using interfaces” is interesting, since that’s anyway something what I’ve always considered to be good way of doing things anyway. I.e. Even up to the point that I’ve to even try to explain this less knowledgeable java developers whom insists using just concrete types always (since it’s makes faster code). Same also with public accessors in classes. I’ve seen in my life far too much code, where developer’s have by default created public accessors and getters for everything, since some bad java programming for beginners book has taught to do so.
Now skipping into reasons, why I strongly force to use interfaces (especially regarding java collections API):
1) Encapsulation: If relevant knowledge is ”List” then restrict it to that, it’s very bad abstraction to state that it’s ”ArrayList” or ”LinkedList”.
2) Performance: Point (1) leads into this. There is small technical details, which in theory give some minor performance advantage for concrete classes over interfaces. In reality, however, it’s interfaces which can get much higher performance boost than concrete type can. Reason is that if interface like ”List” is used, then it’s possible to optimize logic to return optimized List for special cases (ex. single element, empty, or such), while with concrete type such luxury isn’t possible.
3) Inmutability: Yes, interfaces (like List) allow transparent wrapping of collection into inmutable one, ensuring that caller won’t be able to change it
4) Lazy initialization: Yes, it’s easier to manage also lazy initalization with List interface than with ArrayList. With ArrayList, lazy init logic is enforced to allocate concrete ArrayList instance when access is first time done. With List, well, logic is able to just internally keep value as null, but return optimized collection (empty-list, singleton-list, …). This can easily give interface approach 10x speed increase (memory & CPU wise). Especially if serialization is involved (i.e. avoiding serialization of ”empty list” helps a lot). Actually, with very simply utility methods it’s possible to manage lazily initialized (and eagerly deallocated) lists easily (might post example of such some day…).
5) Refactoring: When code is not cluttered with arbitrary dependencies into some specific collection type, it’s much easier to refactor code, and replace implementation, if needed, with more optimal versions.
6) Avoiding fake optimization: For example, it’s too bad that not so accurate java books have stated that using Map.Entry is fastest possible way to iterate over Maps. Now stop for a moment, and think about that a bit, why I say so? If stepping further than such naive assumption, then actually Map API spec isn’t specifying such. Assumption that Map.Entry is fastest approach is based into one implementation of Map (java.util.HashMap), and definitely future java implementations are not making quarantee that such implementation quirk would be true also in the future. So if optimizing code, don’t trust into such ”insider knowledge”.
After saying all that, however, I’ve to say that due to minor performance advantage with concrete types, there is few minor cases were I can allow usage of concrete type. Such cases are some extreme data processing cases, which requires every possible clock cycle what it can get. However, 99,9% cases don’t fall into that category.
There is also another case were concrete types become relevant (actually relevant until interface version are available). Thus I’m talking about collections for primitive types, especially when program starts to use integer/long values outside of very small ”magic cache” inside Integer.valueOf(). Due to this primitive collection types are relevant.
Side note: I’ve to admit that cache of few small integer values in Integer.valueOf() is almost pure evil invention. Reason being the fact that such cache makes small proto test program to fly (since it happens to utilize only small integers value residing on cached range). But then comes actual real data, which contains values outside of that range, and performance dips down drastically (especially since memory usage suddenly explodes through the roof).
Another Side note: Yes, it’s should be self explanatory, that I was participating JFokus 2012…
References:
JFokus 2012 – Presentation: It Is Possible to Do Object-Oriented Programming in Java
JFokus – Presentation: The Art of (Java) Benchmarking
Java Specialists – Polymorphism Performance Mysteries
Java Specialists – Polymorphism Performance Mysteries Explained