Reputation: 1664
I am currently following the examples on Java's Generics on the following page: http://docs.oracle.com/javase/tutorial/java/generics/types.html
public interface Pair<K, V> {
public K getKey();
public V getValue();
}
public class OrderedPair<K, V> implements Pair<K, V> {
private K key;
private V value;
public OrderedPair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
}
Pair<String, Integer> p1 = new OrderedPair<String, Integer>("Even", 8);
OrderedPair<String, Integer> p1 = new OrderedPair<>("Even", 8);
My question is about the lines at the end which create variables. At the very start, one starts with the pair interface, while another starts with the OrderedPair class. Is there a difference whether which one is used? I'm just trying to understand why the code is different.
Upvotes: 0
Views: 78
Reputation: 7799
The code is not valid. Java does not allow two variables of the same name in the same scope.
If names were p1
and p2
, each of them references a different object of class OrderedPair<String,Integer>
. In the second case you were able to omit the generic arguments from the new
because they were already specified with the type of the variable (OrderedPair<String, Integer>
before the variable name). In the first case the type of the object is a subclass of the type of the variable. This is valid per polymorphism. The generic arguments were specified twice, which is also valid though redundant.
As said above, both p1
and p2
reference objects of type OrderedPair<String,Integer>
. However, p1
and p2
have different static (declared) types. In this case, this means that:
OrderedPair
had a method reverseOrder
(just to say something) not inherited from Pair
, then p1.reverseOrder()
would not be valid (even if the referenced object is of the correct type, but the compiler doesn't know this), but p2.reverseOrder()
would be. Here, p2
"is better" than p1
(because you required more specificity and p2
has it).UnorderedPait implements Pair
, new instances of this type could be assigned to p1
, but not to p2
. Here, p1
"is better" than p2
(because you required more generality and p1
has it).Upvotes: 2
Reputation: 79838
If there were methods in the OrderedPair
class that weren't listed in the Pair
interface, then you'd need an expression of type OrderedPair
in order to call them. In other words, you'd want to declare your variable as an OrderedPair
, then call the methods on that variable. On the other hand, if you're only using methods that are listed in the Pair
interface, then you can declare your variable as a Pair
, and call the methods on it. There are two reasons that you might want to do the latter.
Pair
can reference objects of other classes that implement Pair
- you might have UnorderedPair
, PrettyPair
and so on, that are not subclasses of OrderedPair
.Pair
methods of that variable - that any methods that are specific to OrderedPair
won't be used.Upvotes: 0
Reputation: 2155
The first one uses a reference of Pair. With this you can point to any implementation of Pair interface - OrderedPair, SortedPair, LongPair etc.
But with the second reference, you can only point to an object of OrderedPair
Upvotes: 0