我举了一个例子来证明我的问题:
Metrical.java
public interface Metrical<T>
{
double distance(T other);
}
Widget.java
public class Widget implements Metrical<Widget>
{
private final double value;
public Widget(double value) { this.value = value; }
public double getValue() { return value; }
public double distance(Widget other) { return Math.abs(getValue() - other.getValue()); }
}
Pair.java
public class Pair<T>
{
private final double value;
private final T object1, object2;
public Pair(T object1, T object2, double value)
{
this.object1 = object1;
this.object2 = object2;
this.value = value;
}
public T getObject1() { return object1; }
public T getObject2() { return object2; }
public double getValue() { return value; }
}
Algorithm.java
import java.util.Set;
public class Algorithm<T extends Metrical<T>>
{
public void compute(Set<T> objects)
{
}
public void compute(Set<Pair<T>> pairs)
{
}
}
因此,在 Algorithm.java 中, Set&lt;对&LT; T&gt;&gt; 被视为 Set&lt; T&gt; 因此我遇到类型擦除问题。但是,有没有什么办法可以在不命名方法的情况下摆脱这样的事情?这两种算法的变体都是为了在 T 上运行,但我需要允许不同的参数。他们计算同样的事情,所以为了避免混淆,我宁愿不以不同的名字命名。有没有办法容纳这个?
答案 0 :(得分:4)
没有。
你必须记住,有人可以用一个香草集调用你的方法,在这种情况下会调用哪一个?
这就是为什么你不能这样做的原因。就像你不能做的那样:
interface A {
void blah(Set set);
void blah(Set<T> set);
}
同样的问题。
类型信息在运行时不可用(即类型擦除)。
答案 1 :(得分:3)
对不起,坏消息是你不能这样做:
public class Algorithm<T extends Metrical<T>> {
public void compute(Set<T> objects) {
}
public void compute(Set<Pair<T>> pairs) {
}
}
由于擦除,两者都会擦除相同的签名。没有办法解决其中一种方法的重命名问题。
答案 2 :(得分:3)
可悲的是,这是Java Generics倒闭的主要领域......没有好的解决方案。
我通常使用接口为Set<Pair<T>>
创建一个新类,但是包装Set<Pair<T>>
(不扩展它,这会导致同样的问题)。
答案 3 :(得分:0)
我写了一篇关于类型擦除的文章,这可能是你感兴趣的。 它提供了常见的广为人知的解决方案,也是解决问题的棘手方法。 我不知道它是否适合你。无论如何,它包含一些在某些情况下可能有用的技术。
另请参阅:Using TypeTokens to retrieve generic parameters
我希望它有所帮助。
答案 4 :(得分:0)
使用public class Widget<K, P> implements Metrical<K extends Widget<P>>
。
public double distance(Widget other) {}
变为public double distance(Widget<P> other) {}