Warning: you can not make this unseen once you have read

I was talking about the multiple inheritances of default methods in the last blog article and how they behave during compilation and run time. This week I look at how to use default methods to do real inheritance, which actually, default methods were not designed for. For this very reason, please read these lines at your own risk, and do not imply that this is a pattern to be followed, just as well do not imply the opposite. What I write here are some coding technics that can be made using Java 8 but their usability is questionable at least for me. I am also a bit afraid to let some ifrit out of the bottle, but on the other hands, those ifrits just do not stay there anyway. Some day somebody would let it out. At least I attach the warning sign.

Sample problem

A few years ago I worked on an application that used a lot of different types of objects that each had a name. After many classes started to contain

public String getName(){...} public void setName(String name){...}

methods that were just setters and getters the copy-paste code smell just filled the room unbearable. Therefore we created a class

class HasName { public String getName(){...} public void setName(String name){...} }

and each of the classes that had a name, were just extending this class. Actually, it was not working for a long time. There were classes that extended already other classes. In that case, we just tried to move the HasName upward in the inheritance line, but in some cases, it just did not work. As we went up the line reaching for the top we realized that those classes and their some other descendants do not have a name, why to force them? To be honest, in real life it was a bit more complex than just having a name. If it were only names, we could live with it having other classes having names. It was something more complex that would just make the topic even more complicated and believe me: it is going to be complex enough.

Summary: we could not implement having the name for some of the objects implemented in some spare classes. But now we could do that using default methods.

HasName interface with default implementation

Default methods just deliver default functionality. A default method can access the this variable, which is always the object that is implementing the interface and on which behalf the method was invoked. If there is an interface I and class C implements the interface, when a method on a C c object is invoked the variable this is actually the object c . How would you implement getName() and setName() ?

These are setters and getters that accessing a String variable that is in the object. You can not access that from the interface. But it is not absolutely necessary that the value is stored IN the object. The only requirement is that whatever is set for an object the same is get. We can store the value somewhere else, one for each object instance. So we need some value that can be paired to an object and the lifetime of the value has to be the same as the lifetime of the object. Does it ring the bell?

It is a weak hash map! Yes, it is. And using that you can easily implement the HasName interface.

public interface HasName { class Extensions { private static final WeakHashMap<HasName, String> map = new WeakHashMap<>(); } default void setName(String name) { Extensions.map.put(this, name); } default String getName() { return Extensions.map.get(this); } }

All you have to do is write at the end of the list of interfaces the class implements HasName and it magically has.

In this example the only value stored is a String . However, you can have instead of String any class and you can implement not only setters and getters but any methods that do something with that class. Presumably, these implementations will be implemented in the class and the default methods will only delegate. You can have the class somewhere else, or as an inner class inside the interface. Matter of taste and style.

Conclusion

Interfaces can not have instance fields. Why? Because in that case, they were not interfaces but classes. Java does not have multiple implementation inheritance. Perhaps it has but “please don’t use it” kind of. The default method is a technological mistake. You can call it a compromise. Something that was needed to retain backward compatibility of JDK libraries when extended with functional methods. Still, you can mimic the fields in interfaces using weak hash maps to get access to the inherited class “vtable” of fields and methods to delegate to. With this, you can do real multiple inheritances. The type that your mother always warned you about. I told you!

Another warning: the above implementation is NOT thread-safe. If you try to use it in multithread environment you may get ConcurrentModificationException or it may even happen that calling get() on a weak hash map gets into infinite loop and never returns. I do not tell how to fix the usage of weak hash maps in this scenario. Or, well, I changed my mind, and I do: use default methods only the way they were designed for.

If you want to know more about the Java 8 features there is a comprehensive and short tutorial on Java Code Geeks at Java 8 Features Tutorial