JaPerk14
JaPerk14

Reputation: 1664

Invoking generic type

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

Answers (3)

Mario Rossi
Mario Rossi

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:

  1. If type 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).
  2. If you defined a third type 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

Dawood ibn Kareem
Dawood ibn Kareem

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.

  • A variable of type Pair can reference objects of other classes that implement Pair - you might have UnorderedPair, PrettyPair and so on, that are not subclasses of OrderedPair.
  • It tells future maintainers of your program that you are only using the Pair methods of that variable - that any methods that are specific to OrderedPair won't be used.

Upvotes: 0

Crickcoder
Crickcoder

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

Related Questions