为什么在方法中,我可以对参数使用有界通配符,而不对返回类型使用通配符



我找不到更好的问题主题描述,所以我会尽力更好地解释我的问题。我注意到,如果我使用有界通配符;绑定";作为参数,但不是返回值。这听起来可能令人困惑,所以我将立即粘贴我的代码。

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()返回类型<时,这种情况下有什么问题;?扩展对象>。并且清楚地字符串IS-A对象。有人能帮我清理一下吗?

让我们关注两行:

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

对于情况a,没有错误,因为List<? extends Object>正是List<?>

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

  • f((实际上返回了一个List(List<String>是一个List<? extends Object>(——没问题
  • f((实际上返回了一个List(List<Integer>是一个List<? extends Object>(——这可能会导致问题,因为现在b被认为是List<String>,但b.add("foo")会失败

编译器理所当然地担心您可能使用不当。是的,它本可以让您检查是否确实没有调用b.add(),但这会使编译器复杂化,几乎没有什么好处。在许多其他地方,通过验证实际不会发生任何错误,可以避免编译错误,但具有简单的规则("除非明确丢弃,否则没有风险"(会使规则更容易遵循,并且默认为";只允许安全的东西";在很大程度上是Java语言的一部分。

比较:

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

(*(-我使用";编译器";从广义上讲,指的是语言和编译器。

相关内容

  • 没有找到相关文章

最新更新