如何防止类型擦除?

时间:2013-11-27 18:52:55

标签: java generics compilation refactoring type-erasure

我有一个方法,我想重构,它看起来(很好,非常简化)像这样:

import com.sun.tools.javac.util.Pair;

private int foo(Pair<String, ?>... params) {
    if (params[0].snd instanceof String) {
        // do something
        return 0;
    } else if (params[0].snd instanceof ArrayList) {
        // do something else
        return 1;
    }
    return -1; // realistically in the code base, this line will never happen **edit: disregard this line
}

所以我想我会做一些事情,比如把它分成两种方法,这样我就不用做类型检查了。 (这是一个很好的重构吗?)

所以我想做这样的事情:

private int foo(Pair<String, String>... params) {
    // do something
    return 0;
}

private int foo(Pair<String, ArrayList>... params) {
    // do something else
    return 1;
}

但编译器一直告诉我两个foo()方法都有相同类型的擦除。 java只是删除Pair<A, B>知道的所有内容吗?如果是这样,那么重构的最佳方法是什么? (或者是否需要重构)

2 个答案:

答案 0 :(得分:5)

在编译时,Java将erase泛型的类型信息。没有办法阻止这种情况。在运行时,Pair没有<A,B>它实际上是<Object,Object>

至于重构它,有一些你可能更喜欢的东西(但除了一个建议)在你的例子中没有太多可以改进的东西 - 我可能会使用一个其他的(如果最后一行不能我会使用List而不是特定类型的List。

private int foo(Pair<String, ?>... params) {
  if (params[0].snd instanceof String) {
    return 0;
  } else { //if(params[0].snd instanceof List) { //is a List interface, not which List
    // do something else
    return 1;
  }
// return -1; // If it can't happen, why have it here.
}

答案 1 :(得分:1)

我想补充一点

private int foo(Pair<String, String>... params) {
    return 0;
}

private int foo(Pair<String, ArrayList>... params) {
    return 1;
}

如果允许此代码,则没有多大用处。你知道你传入foo的类型。它是引用的类型,而不是实际对象的类型。因此,只需将Pair<String, String>传递给只有0的所有来电替换。

也就是说,调用哪个方法应该在编译时可以确定。不是在运行时。如果它在编译时可以确定,则根本不需要调用该方法。