我试图了解Generics的工作原理并编写了一种方法来测试它。
我创建了Object - Drink及其子对象Coffee ...并定义了一个泛型方法go1()来调用这两个对象的sip()方法......
我在Eclipse中运行并收到错误 - 声明方法sip()未定义为类型V.
有人可以解释一下这是如何处理的吗?
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);
}
}
答案 0 :(得分:3)
只需在类型参数中添加边界:
public static <V extends Drink> void go1(V o){
o.sip();
}
使用类型参数绑定,在这种情况下,您可以使用该类型参数的引用来访问绑定的非静态方法 - Drink
。
修改后:
要将String
和Integer
传递给您的方法,您可以考虑哪个公共上限适合两者。 String
和Integer
的常见超类型为:
所以,你可以有三种界限:
<V extends Object>
<V extends Serializable>
<V extends Comparable<V>>
因此,您只需修改go()
方法,例如:
public static <V extends Object> void go(V v){
System.out.println(v.hashCode());
}
<强>参考文献:强>
答案 1 :(得分:1)
问题是普通<V>
无法理解为Drink
,而是通用Object
。您需要将通用绑定到Drink
类,因此将通用声明为<V extends Drink>
。
答案 2 :(得分:1)
编译器根据调用它们的类型决定方法调用是否有效。
public static <V> V go1(V o){
o.sip();
}
但V
不是有界类型,因此编译器只能确定它至少是Object
类型。 Object
没有sip()
方法。你需要绑定你的类型
public static <V extends Drink> V go1(V o){
o.sip();
}
这样编译器知道V
至少是Drink
类型。 Drink
有sip()
方法。
答案 3 :(得分:1)
只是为了帮助您理解..
鉴于您的总体目标是进一步理解泛型,我只想指出一个简单的接口或超类对象引用将是一个更简单的解决方案。即:
public void go1(Drink d)
{
d.sip();
}
泛型的更经典的例子
假设您有一个对象Pair
。 Pair需要能够在Java中保存两个任何东西,因此你可以创建Object
类型的两个东西。那是什么意思?这意味着您始终在Object
和所需类型之间进行投射。所以你会怎么做?你使用泛型。
public class Pair<F,S>
{
F first;
S second;
public Pair(F first, S second)
{
this.first = first;
this.second = second;
}
}
现在,您只需声明:
,而不是必须施放Pair<Integer, String> pair = new Pair<Integer, String>(10, "Ten");