首页 >Java >java教程 >为什么 Java 中泛型方法上的多个通配符会导致混乱?

为什么 Java 中泛型方法上的多个通配符会导致混乱?

Patricia Arquette
Patricia Arquette原创
2024-11-23 04:03:18725浏览

Why Does Multiple Wildcards on Generic Methods in Java Lead to Confusion?

泛型方法上的多个通配符:Java 编译器难题

简介

Java 泛型中、通配符(*)代表未知类型。当在泛型方法上使用多个通配符时,可能会导致混乱和意外行为。本文探讨了多个通配符的复杂性及其对 Java 类型安全的影响。

混乱

考虑以下代码:

public class TwoListsOfUnknowns {
    static void doNothing(List<?> list1, List<?> list2) { }

    public static void main(String[] args) {
        List<String> list1 = null;
        List<Integer> list2 = null;
        doNothing(list1, list2); // compiles fine!
    }
}

doNothing 中的两个通配符看起来不相关,允许您使用 List 来调用它。和列表。但是,对该方法添加以下内容会出现编译错误:

static void doSomethingIllegal(List<?> list1, List<?> list2) {
    list1.addAll(list2); // DOES NOT COMPILE!!!
}

这表明虽然 list1 和 list2 可以是不同的类型,但它们可能存在某种连接,无法直接使用。

嵌套通配符的混乱

进一步调查发现,混乱不在于多个通配符,而在于嵌套通配符:

public class LOLUnknowns1 {
    static void probablyIllegal(List<List<?>> lol, List<?> list) {
        lol.add(list); // this compiles!! how come???
    }
}

即使 list 可能是与 lol 元素不同的类型,此代码编译也不会出现错误。但是,需要注意的是,这种情况会引发有关类型安全的问题。

真相:捕获转换

这种混乱源于称为捕获转换的概念。它允许某些通配符在泛型方法中使用时捕获特定类型。这就是为什么下面的 possibleIllegal 变体可以编译:

static void probablyIllegalAgain(List<List<? extends Number>> lol, List<? extends Number> list) {
    lol.add(list); // compiles fine!!! how come???
}

这里,lol 中的通配符可以捕获扩展 Number 的类型,例如 List;或列表。这意味着 mightIllegalAgain 可以接受都是数字列表的参数。

理解嵌套通配符

关键要点是多个通配符本身没有问题。当尝试使用嵌套通配符捕获由于类型差异而不“兼容”的类型时,会出现混乱。

对于 LOLUnknowns1,List> 中的嵌套通配符是无法捕获特定类型,因为捕获对于 lol 的所有可能元素类型来说并不安全。这就是为什么 list 可以是任何类型,从而导致潜在的类型安全问题。

结论

泛型方法上的多个通配符可能会令人困惑,但了解捕获转换和它的局限性至关重要。嵌套通配符需要仔细考虑以确保类型安全。通过遵守这些原则,您可以了解 Java 泛型的复杂性并编写健壮的代码。

以上是为什么 Java 中泛型方法上的多个通配符会导致混乱?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn