加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

当类是通用的时,Java通配符奇怪的行为

发布时间:2020-12-15 01:02:49 所属栏目:Java 来源:网络整理
导读:我认为我对 Java泛型有一些很好的理解. 这段代码没有编译,我知道为什么. 我们只能传递给测试方法类型Animal的类型或它的超类型(如对象列表) package scjp.examples.generics.wildcards;import java.util.ArrayList;import java.util.List;class Animal {}cla
我认为我对 Java泛型有一些很好的理解.

这段代码没有编译,我知道为什么.

我们只能传递给测试方法类型Animal的类型或它的超类型(如对象列表)

package scjp.examples.generics.wildcards;

import java.util.ArrayList;
import java.util.List;

class Animal {}
class Mammal extends Animal {}
class Dog extends Mammal {}

public class Test {

    public void test(List<? super Animal> col) {
        col.add(new Animal());
        col.add(new Mammal());
        col.add(new Dog());
    }

    public static void main(String[] args) {
        List<Animal> animalList = new ArrayList<Animal>();
        List<Mammal> mammalList = new ArrayList<Mammal>();
        List<Dog> dogList = new ArrayList<Dog>();

        new Test().test(animalList);
        new Test().test(mammalList); // Error: The method test(List<? super Animal>) in the type Test is not applicable for the arguments (List<Mammal>)  
        new Test().test(dogList);    // Error: The method test(List<? super Animal>) in the type Test is not applicable for the arguments (List<Dog>)

        Dog dog = dogList.get(0);
    }        
}

但这里有一个奇怪的部分(至少对我而言).

如果我们通过仅添加< T>来声明类Test是通用的,那么它就会编译!并抛出java.lang.ClassCastException:

public class Test<T> {
...
}

,

Exception in thread "main" java.lang.ClassCastException: scjp.examples.generics.wildcards.Animal cannot be cast to scjp.examples.generics.wildcards.Dog

我的问题是为什么添加泛型类类型< T> (它没有在任何地方使用)导致类编译和更改通配符行为?

解决方法

表达式new Test()是原始类型. Java语言规范 defines原始类型的成员类型如下:

The type of a constructor (§8.8),instance method (§8.8,§9.4),or non-static field (§8.3) M of a raw type C that is not inherited from its superclasses or superinterfaces is the erasure of its type in the generic declaration corresponding to C. The type of a static member of a raw type C is the same as its type in the generic declaration corresponding to C.

列表的删除<?超级动物>是列表.

这个定义背后的基本原理可能是原始类型旨在作为从非泛型遗留代码使用泛型类型的手段,其中类型参数从不存在.它们没有设计,并且不是最佳的,没有指定类型参数;这就是通配符类型的用途,即如果编写的编译器合规性级别大于1.5,则应编写

Test<?> test = makeTest();
    test.test(animalList);
    test.test(mammalList);
    test.test(dogList);

在再次发现编译错误时欢喜(或诅咒,就此而言).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读