public class SomeClass {
private HashSet<SomeObject> contents = new HashSet<SomeObject>();
private Set<SomeObject> contents2 = new HashSet<SomeObject>();
}
What's the difference? In the end they are both a HashSet
isn't it? The second one looks just wrong to me, but I have seen it frequently used, accepted and working.
One thing worth to mention, is that interface vs. concrete class rule is most important for types exposed in API, eg. method parameter or return type. For private fields and variables it only ensures you aren't using any methods from concrete implementation (i.e. HashSet), but then it's private, so doesn't really matter.
Another thing is that adding another type reference will slightly increase size of your compiled class. Most people won't care, but these things adds up.
Set
is an interface, andHashSet
is a class that implements theSet
interface.Declaring the variable as type
HashSet
means that no other implementation ofSet
may be used. You may want this if you need specific functionality ofHashSet
.If you do not need any specific functionality from
HashSet
, it is better to declare the variable as typeSet
. This leaves the exact implementation open to change later. You may find that for the data you are using, a different implementation works better. By using the interface, you can make this change later if needed.You can see more details here: When should I use an interface in java?
Set
is an interface thatHashSet
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 anotherSet
class in the future, such asLinkedHashSet
orTreeSet
, 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 wasHashSet
.This is Item 52 from Joshua Bloch's Effective Java, 2nd Edition.
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>
issynchronized
, whereasArrayList<T>
(also an implementer ofList<T>
) does not, so if you required synchronized containers in your design (or not), you would need to document that.Since the HashSet class implements the Set interface, its legal to assign a HashSet to a Set variable. You could not go the other way however (assign a Set to a more specific HashSet variable).
Set is a collection interface that HashSet implements.
The second option is usually the ideal choice as it's more generic.