Set
is an interface that HashSet
implements, so if you do this:
Set<E> mySet = new HashSet<E>();
You will still have access to the functionality of HashSet
, but you also have the flexibility to replace the concrete instance with an instance of another Set
class in the future, such as LinkedHashSet
or TreeSet
, or another implementation.
The first method uses a concrete class, allowing you to replace the class with an instance of itself or a subclass, but with less flexibility. For example, TreeSet
could not be used if your variable type was HashSet
.
This is Item 52 from Joshua Bloch's Effective Java, 2nd Edition.
Refer to Objects by their interfaces
... You should favor the use of interfaces rather than classes to refer to objects. If appropriate interface types exist, then parameters, return values, variables, and fields should all be declared using interface types. The only time you really need to refer to an object's class is when you're creating it with a constructor...
// Usually Good - uses interface as type
List<T> tlist = new Vector<T>();
// Typically Bad - uses concrete class as type!
Vector<T> vec = new Vector<T>();
This practice does carry some caveats - if the implementation you want has special behavior not guaranteed by the generic interface, then you have to document your requirements accordingly.
For example, Vector<T>
is synchronized
, whereas ArrayList<T>
(also an implementer of List<T>
) does not, so if you required synchronized containers in your design (or not), you would need to document that.