Java 从列表到列表的两种类型转换方式之间的差异

Java 从列表到列表的两种类型转换方式之间的差异,java,java-8,Java,Java 8,这两种方法有什么区别?一种方法比另一种方法更安全或更快,还是无关紧要?根据Java文档,泛型仅限于编译时。一旦代码编译完毕,它们就会消失,这就是所谓的 现在,关于方法,方法1只是向列表中添加了一个cast,而没有检查列表中所有元素的类型。这意味着,如果列表被强制转换为Cat类型,并且从中得到的是一只狗,那么在运行时代码中的任何地方都可能会出现意外的ClasscastException 方法2创建一个全新的列表,它遍历所有元素,并尝试在目标类型中强制转换每个元素。也就是说,如果所有元素都不能转换为

这两种方法有什么区别?一种方法比另一种方法更安全或更快,还是无关紧要?

根据Java文档,泛型仅限于编译时。一旦代码编译完毕,它们就会消失,这就是所谓的

现在,关于方法,方法1只是向列表中添加了一个cast,而没有检查列表中所有元素的类型。这意味着,如果列表被强制转换为Cat类型,并且从中得到的是一只狗,那么在运行时代码中的任何地方都可能会出现意外的ClasscastException

方法2创建一个全新的列表,它遍历所有元素,并尝试在目标类型中强制转换每个元素。也就是说,如果所有元素都不能转换为目标类型,那么它将失败

我想说方法2是安全的,因为它确保在添加cast之前一切正常,即确定风险。方法1可能允许将包含猫、狗、恐龙的列表强制转换为List,然后,您可能会得到意外的失败


很好地解释了这一点。

不同之处在于,在第一个列表中,您返回相同的列表,而在第二个列表中,您创建了一个新列表

我不认为这两个对象中有一个更“安全”的——因为它最终会在两个对象上都强制转换所有的list objecta,所以非T对象将在两个对象上都导致classCastException


在我看来,第一个更好——不要创建一个相当多余的新列表

鉴于讨论,我想建议一个结合了两个方面优点的选项:它既可以定位不安全演员阵容的风险,又可以避免创建一个新的列表。这很容易。我之所以创建这个社区维基,是因为我只是借用了其他人的想法

步骤1:对方法2中的每个元素进行转换。不要对结果做任何事情,只做演员。这将确保一个错误的值将被提前捕获

步骤2:从方法1执行列表强制转换

还有一个想法
如果您知道从Hibernate获得的列表只包含正确类型的元素,那么您可以继续使用方法1。至少在火星之前的Eclipse JDT在AST中也做了同样的事情。我必须处理原始类型的次数比我希望的要多得多。

无法确定列表是否真的应该包含泛型参数。您必须事先知道参数应该是什么,否则在得到ClassCastException时就会发现。这就是代码生成警告的原因,因为编译器不可能知道它是否安全

如果要支持更通用的数据类型, 那你可以和我一起去

public static <T> List<T> templatizeList(final List list, final Class<T> clazz) {
        return (List<T>) list;
    }

    public static <T> List<T> typeSafeAdd(List<?> from, Class<T> clazz) {
        List<T> to = new ArrayList<>();
        from.forEach(item -> to.add(clazz.cast(item)));
        return to;
    }
否则,, 第二个选项确保它始终是相同的类型,但它会创建新的列表对象


因此,如果您确定,请使用您的第一个解决方案或我的第一个选项,否则,您的第二个解决方案可以删除正在创建新对象的部分。

一个解决方案返回一个新列表,而另一个解决方案返回相同的列表。为什么要从原始类型开始?但是定义更好您必须使用非常旧的Hibernate版本。这取决于您想做什么:是否返回新列表。没有比这更好的了,他们两个都不安全。您完全忽略了源列表中的值类型。这两种方法基本上都是不安全的。因此,建议的做法是不要这样做。如果你真的需要这么做,那么我认为@Darshan Mehta的回答是一个很好的观点。陈述得比保证的要强烈一点。方法2是不安全的,但它确实定位了风险。我想这是最好的了。这正是我想说的。谢谢你的澄清。
public static <T> List<?> templatizeList(final List list, final Class<T> clazz) {
    return (List<?>) list;
}