Core Java

Why to use String

Recently I was tutoring juniors during a training session. One of the task was to write a class that can dwarwle maps based on some string key. The result one of the juniors created contained the following method:
 
 
 
 
 
 
 
 

void dwarwle(HashMap<String,Dwarwable> mapToDwarwle, String dwarwleKey){
		for( final Entry<String, Dwarwable> entry : mapToDwarwle.entrySet()){
			dwarwle(entry.getKey(),entry.getValue(),dwarwleKey);
		}
	}

The code was generally ok. The method to dwarwle an individual dwarwable entry using the actual key it is assigned to in the hash map and the dwarwle key is factored to a separate method. It is so simple that I do not list here. The variable names are also meaningful so long as long you know what actually dwarwling is. The method is short and readable, but the argument list expects a HashMap instead of a Map. Why do we want to restrict the caller to use a HashMap? What if the caller has a TreeMap and for good reason. Do we want to have separate method that can dwarwle TreeMap? Certainly not.

Expect the interface, pass the implementation.

The junior changed the code replacing HashMap to Map but after five minutes or so this clever lady raised her hand and had the following question:

“If we changed HashMap to Map, why did not we change String to CharSequence?”

It is not so easy to answer a question like that when it comes out of the blue. The first thing that came up in my mind is that the reason is that we usually do it that way and that is why. But that is not a real argument, at least I would not accept anything like that and I also except my students not to accept such answer. It would be very dictator style anyway.

The real answer is that the parameter is used as a key in a map and the key of a map should be immutable (at least mutation should be resilient to equals and hashcode calculation). CharSequence is an interface and an interface in Java (unfortunately) can not guarantee immutability. Only implementation can. String is a good, widely known and well tested implementation of this interface and therefore can be a good choice. There is a good discussion about it on stackoverflow.

In this special case we expect the implementation because we need something immutable and we “can not” trust the caller to pass a character sequence implementation that is immutable. Or: we can, but it has a price. If a StringBuilder is passed and modified afterwards our dwarwling library may not work and a blame war may start. When we design an API and a library we should also think about not only the possible but also about the actual, average use.

A library is as good as it is used and not as it could be used.

This can also be applied to other products, not only libraries but this may lead too far (physics and weapon).

Reference: Why to use String from our JCG partner Peter Verhas at the Java Deep blog.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Yannick Majoros
Yannick Majoros
9 years ago

Passing a HashMap to a public method is bad, I generally agree with that. But why would you want to pass a Map around anyway? Even if you can find this kind of design in the wild, this sounds problematic to me, and I’m curious about the real business case.

Peter Verhas
Peter Verhas
9 years ago

Could you elaborate what type of problems we may face passing a Map as method argument? This is not an aggressive question. I understand that it can be a code smell when one has a Map in the API. I acknowledge that Map is a kind of technical interface and not business domain level. This may mean that passing around a Map may be a sign for primitive obsession style. But it is only a smell and passing a Map as a parameter does not inevitable mean that the code is obsessed to primitives. I can easily imagine situation where… Read more »

Back to top button