The underlying principle that governs the answers to your questions is called the Liskov's Substitution Principle which applies in this case to assign the value that is of an instance of a given interface (Collection
, Iterator
) to a reference whose type is a class that implements that interface (e.g. AbstractCollection
, Some anonymous class etc).
If you see the HashMap#values()
method code, you'll see in Java 8 source code:
public Collection<V> values() {
Collection<V> vs;
return (vs = values) == null ? (values = new Values()) : vs;
}
final class Values extends AbstractCollection<V> {
public final int size() { return size; }
public final void clear() { HashMap.this.clear(); }
...
}
Thus, you are being returned either
- an instance of
Values
class which extends an AbstractCollection
which implements Collection
, or
- an instance of a concrete subclass of
AbstractCollection
(see: values = new AbstractCollection<V>()
at line 386
in AbstractMap.java
in Java 8 source code.
Again, according to the LSP, this is all valid. To understand how all this is wired up, you'll need to grok the JDK code base.
More Answers
h.values() returns a Collection view of values in h. Since vals is an interface, how can we assign some values to an interface (they cannot be instantiated)?
To be precise, vals
is not an interface, but an instance thereof. It's true that you can not instantiate an interface say Listener
using the new
operator like listener l = new Listener()
, but according to the LSP, you can always instantiate a concrete implementation of the Listener
interface and assign it to a variable whose type is Listener
, like for example, Listener listener = new SerialListener();
Where is the class that is implementing this interface?
In this case, it is the Values
class or AbstractCollection
class as shown above.
Where is the object of that class?
In several cases, it is an instance of the anonymous inner class that is instantiated at the time of its definition.
We know vals.iterator() returns first element of the collection.
Not quite right. It returns an instance of a class that implements the Iterator
interface. If and when you call the next()
method on the returned object, you get the first element of the collection (assuming it is not empty).
How can we assign it to an interface instance?
The idea is the same. If the variable on the left hand side of an assignment statement (left of =
sign) refers to an interface, then the right hand side can refer to a reference to an object that implements that interface, directly or indirectly (via inheritance hierarchy).