Java类型擦除问题

时间:2009-07-10 00:33:53

标签: java generics types type-erasure

我举了一个例子来证明我的问题:

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 上运行,但我需要允许不同的参数。他们计算同样的事情,所以为了避免混淆,我宁愿不以不同的名字命名。有没有办法容纳这个?

5 个答案:

答案 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) {}