</ p>的差异super / extends String>在方法和变量声明 [英] Difference for <? super/extends String> in method and variable declaration
问题描述
再次,当准备我自己参加OCJP考试时,我偶然发现一个问题,我既不能解释自己也不能找到解释。这是:
Givin:
import java.util。 *;
public class Hancock {
// insert code here
list.add(foo);
}
}
在第5行独立插入的两个代码片段,将编译没有警告? (选择两个)
A。 public void addString(List list){
B. public void addString(List< String> list){
C. public void addString(List<?super String> list){
D. public void addString(List< ;? extends String> list){
正确的答案是B& C。
答案A和B对我来说很清楚。对于答案C&我知道继承的方式,但我不能理解为什么回答D不编译在Eclipse中,而所有其他人做的(一个关于通用,B& C没有warrings)。
在Eclipse中为错误答案D是方法add(capture#1-of?extends String)类型List< capture#1-of? extends String>不适用于参数(String)
。
另一方面,它编译:
public void addString(){
List< ;? extends String> list1 = new ArrayList< String>();
List< ;? super String> list2 = new ArrayList< String>();
}
为什么?为什么< ;?
我知道 String / code>是最终类,不能被任何其他类扩展,但是不能解释这里发生了什么。
public void addString(List< ;? super String> list){
list.add(foo);
}
此方法声明表示您将允许传递 List
由 String
的某个超类进行参数化的对象,例如 String
Object
。所以:
- 如果您通过
List< String>
> $ 如果您通过 - If you pass
List<String>
thelist.add("foo")
will be perfectly valid. - If you pass
List<Object>
thelist.add("foo")
will be perfectly valid, because "foo" is aString
(and you can add aString
to aList<Object>
).
List< Object>
list.add(foo)
将是完全有效的,因为foo是 String
您可以向列表<对象>
)添加 String
。 这意味着答案C是正确的。
回答D。
如果你有这样的方法声明:
public void addString(List< ;? extends String> list){
}
这意味着您将能够传递由 String $ c>的某个未知子类型参数化的列表
$ c>。所以,当你做 list.add(foo);
时,编译器不会知道提供的对象是否具有匹配 unknown < String
的子类型,因此引发了编译时错误。
当您有:
public void addString(){
List< ;? extends String> list1 = new ArrayList< String>();
List< ;? super String> list2 = new ArrayList< String>();
}
这个片段编译正常,因为 list1
定义为保存 String
的某个未知子类型的 List
对象,包括 String
本身,这就是为什么它是有效的。
问题是将无法添加任何,除了 null
。
对于 list2
,变量可以保存由一些超类型参数化的 List
对象 String
,包括 String
本身。
更多信息:
again, while preparing myself for OCJP exam i stumbled upon a question that i can neither explain to myself nor find an explanation. Here it is:
Givin:
import java.util.*;
public class Hancock {
//insert code here
list.add("foo");
}
}
Which two code fragments, inserted independently at line 5, will compile without warnings? (Choose two)
A. public void addString(List list) {
B. public void addString(List<String> list) {
C. public void addString(List<? super String> list) {
D. public void addString(List<? extends String> list) {
Correct answers are B & C.
Answers A and B are quite clear for me. For the answers C & D i know which way the inheritence is going, however i cannot understand why answer D does not compile in Eclipse while all others do (A with warrning about generic, B & C without warrings).
Error in Eclipse for answer D is The method add(capture#1-of ? extends String) in the type List<capture#1-of ? extends String> is not applicable for the arguments (String)
.
On the other hand this compiles:
public void addString() {
List<? extends String> list1 = new ArrayList<String>();
List<? super String> list2 = new ArrayList<String>();
}
Why? Why <? super String>
does not compile in method declaration while it does compile in variable declaration.
I know that String
is final class and cannot be extended by any other class but that does not explain to me what is going on here.
First, let's see answer C:
public void addString(List<? super String> list) {
list.add("foo");
}
This method declaration says that you will be allowed to pass List
objects which are parametrized by some super class of String
, for example String
or Object
. So:
This means that answer C is correct.
Lets now see answer D.
If you have a method declaration like this:
public void addString(List<? extends String> list) {
}
this means that you will be able to pass List
objects parametrized by some unknown subtype of String
. So, when you do list.add("foo");
the compiler won't be aware if the provided object has a type that matches the unknown subtype of String
and therefore raises a compile-time error.
When you have:
public void addString() {
List<? extends String> list1 = new ArrayList<String>();
List<? super String> list2 = new ArrayList<String>();
}
This fragment compiles fine, because list1
is defined to hold List
objects that are of some unknown subtype of String
, including the String
itself, which is why it's valid.
The problem is that you won't be able to add anything, except null
.
As for list2
, the variable can hold List
objects which are parametrized by some super-type of String
, including the String
itself.
More info:
这篇关于</ p>的差异super / extends String>在方法和变量声明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!