When we define a generic class, in the type introduction, each type parameter acts as a placeholder for each unique type that will be passed to either the class initializer or a class method. This means I must pass at least two different data types to the BoxA
class, defined below.
class BoxA<T, S> {
private T t;
private S s;
public void add(T t, S s) {
this.t = t;
this.s = s;
}
public T getFirst() {
return t;
}
public S getSecond() {
return s;
}
}
I have a very difficult time understanding exactly what type parameters mean for generic methods, because they act differently from generic class type parameters for type introduction. For instance:
class Util {
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
return p1.getKey().equals(p2.getKey()) &&
p1.getValue().equals(p2.getValue());
}
}
class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public void setKey(K key) { this.key = key; }
public void setValue(V value) { this.value = value; }
public K getKey() { return key; }
public V getValue() { return value; }
}
I have no idea why the code above works, because if type parameters assume the same role as placeholders as they do for generic class definitions, then the compare method should receive two arguments of differing data types. Instead, each of them receives an argument of type Pair<K, V>
which is also a generic class. What I find difficult to understand is the specific role of K
and V
within public static <K, V> boolean compare(){}
. Are they placeholders for individual types of arguments passed into the method? Are they placeholders for type parameters passed to the actual object-type arguments, which is then passed into the method (i.e. Pair<K, V>
: I view this as one unique type: class Pair<K, V>
that receives two unique type parameters, K
and V
)? Or do generic methods require a unique type parameter for every variable they access whether they are passed as arguments to the method or arguments to an object, which is then passed into the method?
CodePudding user response:
It's hard to understand what exactly you're asking and what exactly you are confused about; I'll try answering your questions anyway.
Type parameters are placeholders for actual types, no matter whether you use them on a class or on a method. Note that this is exactly the same idea as with regular value parameters: they are placeholders for actual values that you supply when you call a method.
public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2)
This is a method with two type parameters, K
and V
, and two value parameters, p1
and p2
.
When you call this method, you'll have to specify actual types for the type parameters, and actual values for the value parameters. In other words: you'll have to specify what types K
and V
are and you'll have to pass two instances of class Pair
for p1
and p2
.
The type parameters are "passed" to the type Pair
in this example. So, the declaration of method compare
means: I have a method named compare
which takes two Pair
objects with type parameters K
and V
. Instead of specifying actual, concrete types, I leave those as parameters. By doing this, you can call compare
with any Pair
with specific types for K
and V
.
For example, you can call compare
with two Pair<Integer, String>
objects. Or two Pair<BigDecimal, Long>
objects, etc.
Are they placeholders for individual arguments passed into the method?
They are placeholders for types, just like regular parameters are placeholders for values.
Are they placeholders for type parameters passed to the actual object-type arguments passed into the method(i.e. Pair<K, V> //I view this as one unique type: class Pair<K, V> that receives two unique type parameters, K and V)?
Yes... (if I understand your question correctly). The method signature means that the method takes two Pair<K, V>
objects, where you leave specifying the actual types to use for K
and V
to the caller of the method.
Or do generic methods require a unique type parameter for every variable they access whether they are passed as arguments to the method or arguments to an object, which is then passed into the method?
I don't understand what you mean by this question.
CodePudding user response:
I works, because compiler does something called type erasure. Basically, during compilation compiler translates generics into non-generic code. Here are docs explaining it in details: https://docs.oracle.com/javase/tutorial/java/generics/erasure.html