有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java中的有界通配符下界泛型即使在传递超类时也不会编译

List<? super IOException>表示列表可以包含IOException对象或IOException类的super对象。那么为什么下面的第2行不编译呢

同样在第3行FileNotFoundException不是IOExceptionsuper类。那为什么要编译呢

List<? super IOException> myList =  new ArrayList<Exception>();
myList.add(new Exception());     //Line 2 This line do not compile
myList.add(new FileNotFoundException());  //Line 3 This compiles

共 (3) 个答案

  1. # 1 楼答案

    这是:

    myList.add(new FileNotFoundException());
    

    编译是因为FileNotFoundException是一个IOException,就像它是一个Exception,所以它满足myList的界限

    这是:

    myList.add(new Exception());
    

    不编译,因为编译器不知道列表的确切类型(它不检查分配给变量的是什么,它只查看它声明的类型),所以它不知道分配给它的列表是否有一个与超级类型IOException匹配的类型,而不是Exception

    如果在ExceptionIOException之间的层次结构中有一个中间类,就会发生这种情况。如果列表实际具有该类型,Exception可能与分配给myList的实际列表的界限不匹配

    编译器不会检查完整的类层次结构,也不会检查分配了什么。它只做基本检查,总是避免运行时错误

    在“逻辑上”没有会导致错误的代码路径,但编译仍然失败的情况下,更普遍的情况也是如此

  2. # 2 楼答案

    myList引用的列表可以是List<IOException>List<Exception>List<Object>。第2行没有编译,因为我们可以有一个List<IOException>和 异常对象不适合放在那里

    File-NotFoundException也可以添加到这三种类型中的任何一种。这很棘手,因为 FileNotFoundExceptionIOException的一个子类,关键字是super

    编译器查看引用类型:List<? super IOException>所有可能的类型,以便:

    List<Object>
    List<Exception>
    List<IOException>
    

    然后它穿过myList.add(new Exception());行,发现它无法编译,因为它无法放入List<IOException>

  3. # 3 楼答案

    通配符下限为类型参数指定下限,而不是为List的可接受类型指定下限。类型参数可以像IOException一样具体,但也可以像我们所能得到的那样一般:Object

    添加Exception时,项的类型作为项太一般,因为类型参数可能太具体,可能是IOException。编译器不允许您向可能只需要IOException秒的内容添加Exception,因此它会生成错误

    这不会发生在FileNotFoundException上,因为无论类型参数有多具体,它都不会比IOException(下限)更具体,因此^{}在所有情况下都是合法的,它是IOException的子类,因此编译器允许它