java - 如果 B 扩展 A,则无法将 List<A> 转换为 List<B> (有道理),但是为什么可以转换 List<?将 A> 扩展到列表 <B>?

标签 java generics casting

如果一个类B扩展类A ,无法施放 List<A>List<B> (下面为 1)。这是有道理的,因为如果允许,那么人们可以读到 B从列表中删除,即使它不包含任何内容。

但是,在下面的代码中,从 List<? extends A> 中转换 2至List<B>引起警告。难道它不应该因为与以前相同的原因而产生错误吗?在代码中,列表仅包含一个对象,即 A但不是B ,但它位于被视为 List<B> 的列表中.

package test;

import java.util.LinkedList;
import java.util.List;

public class TypeLowerBoundCasting {

    static class A {}
    static class B extends A {}

    static void method1() {
        List<A> listOfAs = new LinkedList<A>();
        listOfAs.add(new A());
        // List<B> listOfAsAsListOfBs = (List<B>) listOfAs ; // cast 1: compiler error
        // B b = listOfAsAsListOfBs.get(0); // that would be bad
    }

    static void method2() {
        LinkedList<A> listOfAs = new LinkedList<A>();
        listOfAs.add(new A());
        List<? extends A> listOfAExtensions = listOfAs;
        List<B> listOfAsAsListOfBs = (List<B>) listOfAExtensions; // cast 2: warning, but compiles
        B b = listOfAsAsListOfBs.get(0); // that IS bad; causes a run-time error.
    }

    public static void main(String[] args) {
        method2();
    }
}

最佳答案

一个List<? extends A> 可能List<B> ,这样你就可以转换:

List<? extends A> list = new ArrayList<B>(); // lose type information
List<B> result = (List<B>) list; // regain type information

类似于您可以执行的操作:

Object o = "Hello World!"; // lose type information
String s = (String) o; // regain type information

不幸的是,第一个 Actor 阵容未经检查。但如您所见,在该位置进行强制转换仍然是一个有效的选择。

<小时/>

但是一个List<A>实际上永远不可能成为List<B> (除非你滥用原始类型),因为 List<A>不可从 List<B> 分配(即 List<B> 不会“扩展” List<A> ),因此您无法转换:

List<A> list = new ArrayList<B>(); // Only works with: (List<A>) (List) new ArrayList<B>();

关于java - 如果 B 扩展 A,则无法将 List<A> 转换为 List<B> (有道理),但是为什么可以转换 List<?将 A> 扩展到列表 <B>?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49184280/

相关文章:

Java 和 C++ (VS) RSA 加密

java - 在jTextPane中显示doc文件的内容

java - 在 Java 中将比较器与对象列表一起使用

c++ - 根据条件将基类指针转换为几种可能的派生类型指针之一

Java:线程退出后未回收堆

java - richfaces 过滤日期列

java - 类型删除和重写泛型方法

c# - Array 的通用替代品是什么?

php - 从 SQL 日期时间转换为 PHP DateTime,使用

c++ - 将 std::bind 函数指针转换为 void* 并返回