Reputation: 20856
I'm trying to understand how Generics works and wrote a method to test it.
I have created Object - Drink and its child object Coffee... and defined a generic method go1() to invoke the sip() method of both these objects...
I'm running in Eclipse and get an error - stating the method sip() is undefined for type V.
Can someone explain how this is handled?
class Drink{
public void sip(){
System.out.println("Im Drink method");
}
}
class Coffee extends Drink{
public void sip(){
System.out.println("Im Coffee method");
}
}
public class test{
public static <V> V go1(V o){
o.sip();
}
public static <V> void go(V v){
System.out.println(v.hashCode());
}
public static void main(String[] args) {
Drink s1 = new Drink();
go1(s1);
int i = 10;
String j ="test";
go(i);
go(j);
}
}
Upvotes: 0
Views: 150
Reputation: 213261
Just add bounds to the type parameter:
public static <V extends Drink> void go1(V o){
o.sip();
}
With type parameter bound, you get access to the non-static methods of the bound - Drink
in this case, using the reference of that type parameter.
After edit:
For passing String
and Integer
to your method, you can think of which common upper bound would fit for both. The common supertype for String
and Integer
are:
So, you can have three kinds of bounds:
<V extends Object>
<V extends Serializable>
<V extends Comparable<V>>
So you just modify your go()
method like:
public static <V extends Object> void go(V v){
System.out.println(v.hashCode());
}
References:
Upvotes: 3
Reputation: 27346
Just to aid your understanding..
Given that your overall objective is to further your understanding of Generics, I'd just like to point out that a simple interface or superclass object reference would be a simpler solution to your issue. i.e:
public void go1(Drink d)
{
d.sip();
}
A more classic example of Generics
Let's say you've got an object, Pair
. Pair needs to be able to hold two of anything in Java, so you make those two things of type Object
. What does that mean? It means you're always casting between Object
and the desired type. So what do you do? You use generics.
public class Pair<F,S>
{
F first;
S second;
public Pair(F first, S second)
{
this.first = first;
this.second = second;
}
}
Now instead of having to cast, you simply state:
Pair<Integer, String> pair = new Pair<Integer, String>(10, "Ten");
Upvotes: 1
Reputation: 85779
The problem is that plain <V>
can't be understood as a Drink
but as a generic Object
. You need to bind the generic to your Drink
class, so declare the generic as <V extends Drink>
.
More info: Generic Methods and Bounded Type Parameters
Upvotes: 1
Reputation: 279990
The compiler decides if method calls are valid based on the type they are called on. You have
public static <V> V go1(V o){
o.sip();
}
but V
is not a bounded type so the compiler can only be sure that it is at least of type Object
. Object
doesn't have a sip()
method. You need to bound your type
public static <V extends Drink> V go1(V o){
o.sip();
}
This way the compiler knows that V
is at least of type Drink
. Drink
has a sip()
method.
Upvotes: 1