当前位置: 首页 > 知识库问答 >
问题:

为什么我可以对参数使用有界通配符,而不能对方法中的返回类型使用有界通配符?[副本]

茅秦斩
2023-03-14

我找不到更好的描述我的问题的主题,所以我会尝试更好地解释我的问题。我注意到,如果我使用有界通配符,我可以使用它的“bound”作为参数,但不能作为返回值。这可能听起来很混乱,所以我将直接粘贴我的代码。

public static void main (String[] args) {
    List<?> wildcardList = new ArrayList<> ();
    List<String> stringList = new ArrayList<> ();
    takeList (wildcardList); //compiles
    takeList (stringList); //compiles
    /////////////////////////////////////
    List<?> wildcard = returnList (); //compiles
    List<String> strings = returnList (); //doesn't compile

}

static void takeList(List<? extends Object> list){
    //some code
}

static List<? extends Object> returnList(){
    return new ArrayList<> ();
}

我想知道为什么最后一行代码不能编译。当我显式地说returnList()的返回类型是<时,这个问题是什么?extends Object>。很明显String是一个对象。有人能帮我把这事弄清楚吗?

共有1个答案

冯宏恺
2023-03-14

让我们集中在两条线上:

// f() returns a List<? extends Object>
List<?>      a = f(); // ok: can never do unexpected things
List<String> b = f(); // error: not 100% safe

对于大小写a,没有错误,作为列表<?extends Object>正是一个列表<?>

对于caseb,Java编译器*的问题是,如果允许执行赋值,是否会生成任何类型的意外错误(类转换)。让我们看看一些例子:

    null

编译器有理由担心您可能使用不当。是的,它可以允许您继续检查,确实,您没有调用b.add()--但这会使编译器复杂化,而没有什么好处。在许多其他地方,可以通过验证实际不会发生什么坏事来避免编译错误,但是拥有简单的规则(“除非明确放弃,否则没有风险”)使规则更容易遵循,并且默认为“只允许安全的东西”是Java语言的很大一部分。

要比较:

// f() returns a float
float a = f(); // ok
int   b = f(); // error: not 100% safe, unwanted rounding may result!

(*)-我使用“编译器”是广义的,既指语言也指编译器。

 类似资料:
  • 问题内容: 最近,我读了这篇文章:http : //download.oracle.com/javase/tutorial/extra/generics/wildcards.html 我的问题是,而不是创建像这样的方法: 我可以创建一个这样的方法,它可以正常工作: 我应该使用哪种方式?通配符在这种情况下有用吗? 问题答案: 这取决于您 需要 做什么。如果要执行以下操作,则需要使用bounded t

  • 问题内容: 我在很多地方都读过,包括在方法返回类型中使用有界通配符是一个坏主意。但是,我在课堂上找不到避免这种情况的方法。我想念什么吗? 情况看起来像这样: 总而言之,这是一个我希望能够 使用 任何与英语有所不同的出版物的类。该类需要允许从外部访问发布,但理想情况下,的调用者不希望将结果用作有界通配符。他们会很高兴的。 有办法解决吗? 问题答案: 有界通配符具有传染性,这就是您链接到的页面似乎在哀

  • 在了解Java泛型的过程中,我遇到了以下问题: 假设我有下面的方法来添加列表的元素,只限于包含数字的列表。 但是这段代码和这段代码有什么不同: 它们都按预期编译和执行。这两者之间有什么区别?除了语法之外?什么时候我更喜欢使用通配符而不是前者? 是的,使用通配符方法,我不能在列表中添加除null之外的新元素,否则它将无法编译。除此之外呢?

  • 问题内容: 是否可以在方法的返回参数中使用通用通配符类型,这是否可行? 换句话说,确实可以像下面这样声明一个接口: 另外,可以说通用通配符类型仅在方法的 参数声明 时才有意义吗? 问题答案: 使用通配符类型(例如在方法正式参数中)的主要好处是为用户提供了灵活性,使其可以传递任何类型的,或任何实现Collection的东西(假设collection声明为)。您通常会发现自己在形式参数中使用通配符类型

  • 问题内容: 摘自Effective Java Chapter 5(泛型): 这两个声明中的哪一个是可取的,为什么?在公共API中,第二个更好,因为它更简单。您传入一个列表(任何列表),该方法交换索引元素。没有类型参数值得担心。通常,如果类型参数在方法声明中仅出现一次,则将其替换为通配符。 我不明白,为什么第二个选项对我的API客户端来说更简单?我可以将相同的参数传递给第一个和第二个方法。第二种方法

  • 根据Joshua Bloch的“有效Java”一书,关于如何/何时在泛型中使用有界通配符有一个规则。这个规则就是PECS(productor-extends,Comsumer-Super)。当我研究以下示例时: 根据PECS规则,上述声明是错误的。但是我希望有一个的,并向这个传递一个。为什么不做呢? 为什么要始终使用关键字?为什么使用是错误的? 当然,这也代表了Comsumer的观点。为什么消费者