繁体   English   中英

在方法参数中使用通配符

[英]Using wildcard in method argument

我已经声明了一个方法,其参数是Number子类型,如下所示:

public static void organizeData(java.util.List<? extends Number> c) {
    //operation on the list
}

我可以将任何非参数化列表作为参数传递。 那么使用通配符<? extends Number> <? extends Number>

List newList = new LinkedList<>();
ClassName.organizeData(newList);

为什么我从c获取Object类型的元素? 而不是Number类型? 有没有办法只允许一种类型的子类型作为参数传递,而不允许非参数化的参数呢?

你在这里问三个问题,我将分别回答。 顺便说一下,你会发现阅读Java Generics FAQ很有价值- 被许多人认为是关于这个主题的规范参考

  1. 那么使用通配符<? extends Number> <? extends Number>

当参数化参数是Number的子类(例如, Integer时,您需要使用通配符。 例如:

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

public class NumberTest {
    public static void main(String... args) {
        List<Integer> newList = new LinkedList<Integer>();
        organizeData(newList); // This works!
        anotherMethod(newList); // Doesn't compile
    }

    private static void organizeData(List<? extends Number> list) {

    }

    private static void anotherMethod(List<Number> list) {

    }
}

第二个方法调用因编译错误而失败:

NumberTest.java:9: error: method anotherMethod in class NumberTest cannot be applied to given types;
                        anotherMethod(newList); // Doesn't compile
                        ^
  required: List<Number>
  found: List<Integer>
  reason: actual argument List<Integer> cannot be converted to List<Number> by method invocation conversion
1 error

  1. 为什么我从c获取Object类型的元素? 而不是Number类型?

在第二种情况下获得一种Object类型的原因是因为您使用的是Raw Type。 如果由于这个原因可以避免使用原始类型,则永远不应该使用原始类型 - 您将失去编译器类型检查的所有优点。


  1. 有没有办法只允许一种类型的子类型作为参数传递,而不允许非参数化的参数呢?

您不能以您描述的方式阻止堆污染 ,因为有人总是可以转换为Raw类型,然后转换为所需的任何内容。 泛型是仅编译时构造,并且在编译后最终被擦除。 这就是为什么只能通过注释来抑制未选中类型转换警告的原因。

您必须记住,Java泛型是一个编译时构造,以帮助进行类型安全。 在运行时,类型擦除会将所有泛型类型转换为Object并在需要时添加转换。 如果通过使用原始类型(编译器为其提供警告)绕过编译时检查,则绕过了泛型的好处(编译时类型检查和运行时安全转换)。

Java中的泛型是通过Type erasure实现的。 ie:您在<>中指定的类型信息在运行时期间不存在。 在编译期间,java编译器利用<>中给出的信息来确保一切都井然有序。 但是,如果您没有在变量'newList'中指定<>中的类型,则无法阻止您将其传递给'organizeData'方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM