0

问题:

当从子类访问时,参数化类的对象被视为非泛型。我该如何克服呢?

细节:

考虑一个基类:

public class MyBaseClass {
    protected List<Number> numbers = new ArrayList<Number>();

    public MyBaseClass(){
        //...
    }
}

现在,让我们扩展这个类:

public class MyDerivedClass extends MyBaseClass {

    public void addSomething() {
        numbers.add(25.0f); //Warning about type-safety here
    }
}

在派生类中,数字对象被视为原始类型。警告是:

类型安全:方法 add(Object) 属于原始类型 List。对泛型类型 List 的引用应该被参数化。

如果我尝试自己添加类型参数,则会出现编译错误:

        numbers.<Number>add(25.0f); //Error here

我看到的错误是:

List 类型的方法 add(Number) 不是通用的;它不能用参数参数化

但是,如果我将这两个类放在同一个 Java 源文件中,那么这个问题就会消失。首先没有警告。这是说明问题的示例。

在我的实际应用程序中,我希望能够从List派生类中获取元素,并对它们执行特定于类的操作,而不必先将检索到的对象转换为适当的类型。

我怀疑问题是因为类型擦除,但我不知道如何解决它。


编辑:

我在 Fedora Core 16 上使用 Eclipse 3.7.2 和 Oracle JDK 1.6.0_30。编译器合规性设置为 1.6,默认合规性设置。正如我所提到的,如果我将两个类放在同一个 .java 文件中,那么我看不到警告。仅当我将它们放在不同的文件中时才能看到。

我可以通过定义所有直接对父类中的列表对象进行操作的方法来解决这个问题;并从派生类中使用它。

但我仍然很好奇为什么我会看到警告。这是解决方法:

在 MyBaseClass 中:

    protected void addNumberToList(Number num){
        numbers.add(num);
    }

然后在派生类中:

    public void addSomething() {
        addNumberToList(25.0f);
    }

同样,所有直接操作List对象的操作都可以在基类中。

4

2 回答 2

3

真正的基类是通用的,但您的子类继承自其原始类型:

public class MyBaseClass<X> {
    protected List<Number> numbers = new ArrayList<Number>();

    public List<Number> getNumbers() {
        return numbers;
    }
}

public class MyDerivedClass extends MyBaseClass {
    public void addSomething() {
        numbers.add(25.0f);
    }
}

JLS §4.8说成员访问将被视为原始类型。这意味着numbers被视为原始,因此发出警告。解决方案是参数化超类型:

public class MyDerivedClass extends MyBaseClass<TypeArgumentsHere>
于 2012-06-21T07:58:46.470 回答
0

我使用 Eclipse 并且您的代码很好地遵守了,没有警告或错误。但我认为您应该提供protected/public方法而不是公开实例变量。

public class MyBaseClass {
    protected List<Number> numbers = new ArrayList<Number>();

    public List<Number> getNumbers() {
        return numbers;
    }
}

public class MyDerivedClass extends MyBaseClass {

    public void addSomething() {
        getNumbers().add(25.0f);
    }
}
于 2012-06-21T07:17:20.177 回答