繁体   English   中英

类型擦除和继承:List的对象 <Number> ,当从子类访问时被视为原始列表?

[英]Type erasure and inheritance: An object of List<Number> , when accessed from a sub-class is seen as a raw List?

题:

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

细节:

考虑一个基类:

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对象的所有操作都可以在基类中。

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

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被视为原始numbers ,因此是警告。 解决方案是参数化超类型:

public class MyDerivedClass extends MyBaseClass<TypeArgumentsHere>

我使用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);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM