首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型擦除和继承:当从子类访问时,List<Number>的一个对象被视为原始列表?

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

Stack Overflow用户
提问于 2012-06-21 07:10:46
回答 2查看 452关注 0票数 0

问题:

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

详细信息:

考虑一个基类:

代码语言:javascript
复制
public class MyBaseClass {
    protected List<Number> numbers = new ArrayList<Number>();

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

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

代码语言:javascript
复制
public class MyDerivedClass extends MyBaseClass {

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

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

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

如果我自己尝试添加类型参数,就会得到一个编译错误:

代码语言:javascript
复制
        numbers.<Number>add(25.0f); //Error here

我看到的错误是:

类型列表的add(Number)方法不是泛型的;它不能用参数进行参数化。

但是,如果我将两个类都放在同一个Java源文件中,那么这个问题就没有了。从一开始就没有警告。这是一个例子来说明这个问题。

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

我怀疑问题是因为类型擦除,但我想不出如何解决这个问题。

编辑:

我在Fedora 16上使用Eclipse3.7.2和Oracle 1.6.0_30,编译器遵从性设置设置为1.6。如前所述,如果我将两个类放置在同一个.java文件中,则不会看到警告。只有当我将它们放在不同的文件中时才能看到。

我可以通过定义直接在父类中的list对象上操作的所有方法来解决这个问题;并使用派生类中的方法。

但我还是很好奇为什么我会看到这个警告。这是一个解决办法:

在MyBaseClass中:

代码语言:javascript
复制
    protected void addNumberToList(Number num){
        numbers.add(num);
    }

然后在派生类中:

代码语言:javascript
复制
    public void addSomething() {
        addNumberToList(25.0f);
    }

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

EN

回答 2

Stack Overflow用户

发布于 2012-06-21 07:58:46

真正的基类是泛型的,但是您的子类继承自它的原始类型:

代码语言:javascript
复制
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被视为raw,因此出现了警告。解决方案是将超级类型参数化:

代码语言:javascript
复制
public class MyDerivedClass extends MyBaseClass<TypeArgumentsHere>
票数 3
EN

Stack Overflow用户

发布于 2012-06-21 07:17:20

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

代码语言:javascript
复制
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);
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11133214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档