I recently ran across a set of code which instantiated local maps as following:
HashMap<String, Object> theMap = new HashMap<String, Object>();
Typically, when I've seen HashMaps used (and used them myself), the local variables are simply Map (the interface), rather than being tied to the specific implementation. Obviously this is required if the Map could potentially be instantiated as various Map types (e.g. accepting a parameter). However, in the case of something like the above where it's defined and instantiated at the same point, is there an underlying reason to only use the interface type, or is it simply style/convention?
(I originally misunderstood the question based on the title, but I've included both type and variable conventions as both are interesting.)
What's important is that it's a map: something you look things up in. The rest is an implementation detail.
I would suggest giving it a semantic name, e.g.
Map<String, Object> nameToSessionMap = ...
... that way when you read the code, you'll know what the keys and values are meant to be.
As for the type of the variable - again, I'd typically use the interface rather than the implementation partly because it indicates I'm not using any members which are specific to the type. I don't want to emphasize the implementation in the code, usually... it means when I do care about the implementation, I can make that more obvious.
Declaring the object as a Map will allow the compiler to protect you from calling methods which are specific to HashMap. This will allow you to substitute another Map implementation in the future without worrying about having method calls which do not exist in the Map interface.
In general people use mostly Map to make the least amount of assumptions on the implementation.
It cannot be that the Classname is used for the additional methods as only clone() is added by HashMap, which has fallen in disuse (for good reasons).
What could be is that the map needs to be Serializable for one reason or another, and the plain Map interface does not extend it, but HashMap does implement it.
Even in this case, it keeps it generic. Coding to interface ensures you are using a Map and not a specific implementation of it.
Related
I don't understand this code Map<E, Integer> d = new HashTable<E, Integer>(list.size()); : we create a new object but is it a map or a hashtable? what is the difference between the both of them? I thought that a map is just a way to put 2 element together like a key and its value (for exemple {3; Detroit})
is it a map or a hashtable?
Yes.
The static, compile time type of the reference is Map. As others have already pointed out, it's an interface. You can call all the methods on the Map interface and know that they'll obey the contract and behave as describe.
The dynamic, run time type of the object reference refers to is Hashtable. It implements all the methods in the Map interface in its own way.
The key idea is that the compile time type of a reference is separate from the run time type of the object on the heap that it points to.
Hashtable is a JDK 1.0 class that sticks around for compatibility reasons. It's been retrofitted to implement the Map interface, which was introduced later. You'd be well advised to choose another implementation, such as HashMap, depending on your requirements.
The last part of Hashtable contains the reason why it should not be used:
As of the Java 2 platform v1.2, this class was retrofitted to implement the Map interface, making it a member of the Java Collections Framework. Unlike the new collection implementations, Hashtable is synchronized. If a thread-safe implementation is not needed, it is recommended to use HashMap in place of Hashtable. If a thread-safe highly-concurrent implementation is desired, then it is recommended to use ConcurrentHashMap in place of Hashtable.
This means that it is less efficient than HashMap for single-thread models and less efficient than ConcurrentHashMap for multi-threaded models.
Understanding how compile and run time types differ is crucial to understanding how object oriented polymorphism works. This is true for all OO languages: C++, Java, .NET, Python, etc.
Map is an interface. Hashtable is one of the classes that implements the Map interface.
See the Java Doc for the Map interface. Specifically the section that says all known implementing classes.
Any class that implements a Map provides a key->value data-structure. A Map being an interface defines the contract that all implementing classes must adhere to. By itself, a Map cannot be instantiated.
Note that while Hashtable should ideally have been named as HashTable following the java naming conventions, this is is a pre-historic class in Java which exists even before the standard java naming conventions came into existence. Therefore, it is still called Hashtable and not HashTable as wrongly mentioned in your question.
Map is an interface. HashTable is one implementation of that interface. There are several others, such as HashMap, SortedMap, etc. The interface defines the programming API; the implementation defines how that API is implemented. Different implementations may have different runtime performance characteristics.
With regard to interfaces vs. implementations, you may find my answer to Java - HashMap vs Map objects here helpful.
Could any one explain,what is the difference between creating reference name using Object or using Interface.
ex1
ArrayList li=new ArrayList();// creating reference using class name
ex2
List li=new ArrayList()//creating reference using interface name
In real scenario why developers using ex2?
What are the advantages for using ex2?
The second approach is programming to an interface. It makes it clear that although you may be dependent on some aspects of the behaviour of the chosen implementation (e.g. its performance characteristics, or its sort order etc) you're only relying on the members declared in the interface. This generally makes it easier to later swap out one implementation with another.
(If you are relying on some very specific aspect of an implementation, I find it's usually a good idea to explicitly say so, to avoid surprises later.)
It means you are coding to a contract and not an implementation. In your example the List contact. If later you need a different type of list all you need to do is change one line where you make your declaration. It makes making changes in the future easier.
If you need specific methods on ArrayList that aren't in list then using ex1 is valid. Although if you change from ArrayList it may be harder. This link may be useful http://jdevelopment.nl/java-best-practices-5-code-to-interface-access-by-name-and-instance-data/
The second has much more advantages:
It is considered good style to store a reference to a HashSet or TreeSet in a variable of type Set. For example:
Set<String> names = new HashSet<String>();
This way, you have to change only one line if you decide to use a TreeSet instead.
Also, methods that operate on sets should specify parameters of type Set:
public static void print(Set<String> s)
Then the method can be used for all set implementations.
I am implementing the Map<V,K> and the Collection<V> interface in one class, but the remove(Object) method occurs in both interfaces, therfore eclipse shows me some errors. The return types are different, one returns boolean and the other V but that doesn't seem to matter.
Is there some way of telling java/eclipse which method is actually being overridden?
EDIT: I have got an interface that all values must implement, it supplies the value with a getKey() method, making it possible to write an add function for the map. But there seems to be no way to let this one class look as a map and a collection at the same time?
No, there is no a direct way.
Actually dynamic binding takes into account the signature excluding the returning type so Java compiler cannot accept the two methods for the same class that have same signature but different return types. If two methods have same names and same parameters than they MUST also have same returning type, unfortunately for you.
The only way is to split the behavior in two different classes and composing them. Maybe a method like Collection<V> asCollection() or something like that.
The Map already has keySet() which is collection of keys. Why do you need the Collection also? If it's so, just do two methods like asMap and asCollecton which do return different types.
No, there isn't a way to resolve such conflicts.
You should consider to use composition and delegation instead of inheritance for at least one of the two interfaces, or you could split the functionality of your class in two classes, it really depends on your concrete problem.
You probably need composition instead of inheritance. Unfortunately Java has no language-level support for that - I mean it can be done but it is unnecessarily laborious.
You need to rethink your design. Fundamentally, a map is different to a collection. Think about the Collection.add() method. Does it make any sense to add an object without a key or a key without a value to a map?
Your best bet (I think and depending on your application) is to implement a map but when you need a collection, use one of its methods to get the set of keys, values or key value pairs.
This has been bugging me for a while and have yet to find an acceptable answer. Assuming a class which is either a subclass or implements an interface why would I use the Parent class or Interface as the Type i.e.
List list = new ArrayList();
Vehicle car = new car();
In terms of the ArrayList this now only gives me access to the List methods. If I have a method that takes a List as a parameter then I can pass either a List or an ArrayList to it as the ArrayList IS A List. Obviously within the method I can only use the List methods but I can't see a reason to declare it's type as List. As far as I can see it just restricts me to the methods I'm allow to use elsewhere in the code.
A scenario where List list = new ArrayList() is better than ArrayList list = new ArrayList() would be much appreciated.
You write a program that passes lists around several classes and methods. You now want to use it in a multi threading environment. If you were sensible and declared everything as List, you can now make a single change to one line of code:
List list = Colllections.synchronizedList(new ArrayList());
If you had declared the list as an ArrayList, you would instead have to re-write your entire program. The moral of the story - always program to the least restrictive interface that your code requires.
Using the interface or parent type is generally recommended if you only need the functionality of the parent type. The idea is to explicitly document that you don't really care about the implementation, thus making it easier to swap out the concrete class for a different one later.
A good example are the Java collection classes:
If you always use List, Set etc. instead of e.g. ArrayList, you can later switch from ArrayList to LinkedList if you find that it gives e.g. better performance. To do that, just change the constructors (you don't even have to change them all, you can mix). The rest of the code still sees an instance of List and continues working.
If you actually used ArrayList explicitly, you'd have to change it everywhere it's used. If you don't actually need an ArrayList specifically, there's nothing to be gained from using it over the interface.
That's why it's generally recommended (e.g. in "Effective Java" (J.Bloch), Item 52: "Refer to Objects by their interfaces".) to only use interfaces if possible.
Also see this related question: Why classes tend to be defined as interface nowadays?
The key is exactly that the interface or base class restricts what you can do with the variable. For example, if you refactor your code later to use another implementation of that interface or base class, you won't have anything to fear -- you didn't rely on the actual type's identity.
Another thing is that it often makes reading the code easier, e.g. if your method's return type is List you might find it more readable to return a variable of type List.
An interface specifies a contract (what does this thing do), an implementation class specifies the implementation details (how does it do it).
According to good OOP practice, your application code should not be tied to implementation details of other classes. Using an interface keeps your application loosely coupled (read: Coupling)
Also, using an interface lets client code pass in different implementations and apply the decorator pattern using methods like Collections.synchronizedList(), Collections.unmodifiableList() etc.
A scenario where List list = new
ArrayList() is better than ArrayList
list = new ArrayList() would be much
appreciated.
One concrete example: if it's a field declaration and you have a setList(), which of course should take a List parameter to be flexible.
For local variables (and fields with no setters), there is very little concrete benefit in using the interface type. Many people will do it anyway on general principle.
You were right. In these cases, the variables are fields or local variables, they are not public interface, they are implementation details. Implementation detail should be detailed. You should call an ArrayList an ArrayList, because you just deliberately chose it for your implementation.
People who recycle cliches: look at your post and think a little bit more. It's nonsense.
My previous answer that was downvoted to death:
Use interface or type for variable definition in java?
The java.util.Properties class is meant to represent a map where the keys and values are both Strings. This is because Properties objects are used to read .properties files, which are text files.
So, why in Java 5 did they retrofit this class to implement Map<Object,Object> and not Map<String,String>?
The javadoc states:
Because Properties inherits from Hashtable, the put and putAll methods can be applied to a Properties object. Their use is strongly discouraged as they allow the caller to insert entries whose keys or values are not Strings. The setProperty method should be used instead. If the store or save method is called on a "compromised" Properties object that contains a non-String key or value, the call will fail.
Since the keys and values are both supposed to be Strings then why not enforce that statically by using the proper generic type?
I guess making Properties implement Map<String,String> would not be fully backward compatible with code written for pre-Java 5. If you have older code that sticks non-strings into a Properties object then that code would no longer compile with Java 5. But... isn't that a good thing? Isn't the whole point of generics to catch such type errors at compile time?
Because they did it in a hurry in the early days of Java, and didn't realise what the implications would be four versions later.
Generics were supposed to be part of the design of Java from the beginning, but the feature was dropped as being too complicated and, at the time, unnecessary. As a result, lots of code in the standard libraries is written with the assumption of non-generic collections. It took the prototype language "Pizza" from Martin Odersky to show how they could be done fairly well while maintaining near perfect backwards compatibility, with both Java code and bytecode. The prototype led to Java 5, in which the collections classes were retrofitted with generics in a way that allowed old code to keep working.
Unfortunately, if they were to retroactively make Properties inherit from Map<String, String>, then the following previously valid code would stop working:
Map<Object, Object> x = new Properties()
x.put("flag", true)
Why anybody would do that is beyond me, but Sun's commitment to backwards compatibility in Java has gone beyond heroic into the pointless.
What's now appreciated by most educated observers is that Properties should never have inherited from Map at all. It should instead wrap around Map, exposing only those features of Map that make sense.
Since reinventing Java, Martin Odersky has gone on to create the new Scala language, which is cleaner, inherits fewer mistakes, and breaks new ground in a number of areas. If you're finding Java's niggles annoying, take a look at it.
It was originally intended that Properties would indeed extends Hashtable<String,String>. Unfortunately the implementation of bridge methods caused a problem. Properties defined in such a way causes javac to generate synthetic methods. Properties should define, say, a get method that returns a String but needs to override a method that returns Object. So a synthetic bridge method is added.
Suppose you had a class written in the bad old 1.4 days. You've overridden some methods in Properties. But what you haven't done is overridden the new methods. This leads to unintended behaviour. To avoid these bridge methods, Properties extends Hashtable<Object,Object>. Similarly Iterable does not return a (read-only) SimpleIterable, because that would have added methods to Collection implementations.
A one-liner (two-liner for no warnings) for creating Map from Properties:
#SuppressWarnings({ "unchecked", "rawtypes" })
Map<String, String> sysProps = new HashMap(System.getProperties());
Backwards compatibility.
The reason: Liskov substitution principle and backwards compatibility. Properties extends Hashtable and thus must accept all messages that Hashtable would accept - and that means accepting put(Object, Object). And it has to extend plain Hashtable instead of Hashtable<String, String> because Generics were implemented in the downwards-compatibe way via type erasure, so once the compiler has done its thing, there are no generics.