If you wanted to store an array of objects of type MyInterface
, are the following both acceptable and if so when would you use the second form over the first?
如果您想要存储MyInterface类型的对象数组,是否可以接受以下内容,如果可以,什么时候在第一个表单中使用第二个表单?
i) Using only an interface:-
i)只使用一个接口:-
List<MyInterface> mylist = new ArrayList<MyInterface>();
ii) Using a generic wildcard:-
使用通用通配符:-
List<? extends MyInterface> mylist = new ArrayList<? extends MyInterface>();
Edit:
编辑:
As the answers so far have pointed out, number ii won't compile. What is the difference between i and a case iii where :-
正如目前为止的答案所指出的那样,第二种方法不会被编译。我和案例三的区别在哪里:- ?
iii) Using a generic wildcard only in the reference:-
iii)仅在引用中使用泛型通配符:-
List<? extends MyInterface> mylist = new ArrayList<MyInterface>();
5 个解决方案
#1
7
Second one won't compile. Imagine:
第二个不会编译。想象一下:
A implements MyInterface
B implements MyInterface
Then the following would match your second expression, but won't compile:
然后下面的语句将匹配您的第二个表达式,但不会编译:
// incorrect
List<A> mylist = new ArrayList<B>();
Correction: Wrong one too:
更正:错误的:
List<? extends MyInterface> mylist = new ArrayList<MyInterface>();
It is right in a sense it does compile, but you cannot add any subclasses of MyInterface to it. Confusing, but correct -- after I read the explanation. Same reason: wildcard can be viewed for example as:
从某种意义上说,它确实可以编译,但是不能向它添加任何MyInterface的子类。困惑,但正确——在我读了解释之后。同样的原因:可以查看通配符,例如:
// I know this is not compileable; this is internal compiler "thinking".
// Read it as "somewhere someone may instantiate an ArrayList<A> and pass
// it down to us; but we cannot accept it as something that could be
// potentially used as List<B>"
List<A> mylist = new ArrayList<MyInterface>();
So this won't work:
这是行不通的:
mylist.add(b);
and vice versa. Compiler refuses to do those potentially incorrect operations.
反之亦然。编译器拒绝执行那些潜在的错误操作。
The option which allows you to add any subclass of MyInterface to mylist is:
可以添加MyInterface myto mylist任何子类的选项是:
List<MyInterface> mylist = new ArrayList<MyInterface>();
#2
4
If you would like to store the ojects of type MyInterface
the better (and compilable) approach would be -
如果您想存储MyInterface类型的对象,更好的(和可编译的)方法是-
List<MyInterface> mylist = new ArrayList<MyInterface>();
But if you would like to use in the method parameter then you can use option 2 (bounded wildcard type) for API flexibility.
但是如果您想在方法参数中使用,那么您可以使用选项2(有界通配符类型)来实现API的灵活性。
public void someMethod(List<? extends MyInterface> myInterfaces);
EDIT:
The above code will give the more flexibility API because Generic types are invariant, so if you have -
编辑:上面的代码将提供更灵活的API,因为泛型类型是不变的,所以如果您有-
public class A implements MyInterface {
// some implementation
}
and if someMethod
has a parameter type List<MyInterface>
then it won't be able to take the List<A>
, this forces API users to create List
with type MyInterface
on the other side - List<? extends MyInterface>
will allow to pass List<A>
to someMethod
.. client usually has a List<ActualObject>
so it's more flexible to provide a parameter which will take any implementation of MyInterface
At the same time do not use wildcard types as return types like
如果someMethod有一个参数类型列表
public List<? extends MyInterface> someMethod();
If the user of a class has to think about wildcard types, there is probably something wrong with the class’s API.
如果一个类的用户必须考虑通配符类型,那么这个类的API可能有问题。
#3
4
List<? extends MyInterface>
means a list of some subtype of MyInterface
, but we don't know which subtype.
列表< ?扩展MyInterface>表示MyInterface的某个子类型的列表,但是我们不知道是哪个子类型。
Since we don't know which subtype is used actually, we can't put any object in it (as we can't ensure that it is an element of this subtype).
因为我们不知道实际使用的是哪个子类型,所以我们不能在其中放入任何对象(因为我们不能确保它是该子类型的元素)。
We can take objects out of such a list, and know that it is an object implementing MyInterface
, but nothing more.
我们可以从这样的列表中取出对象,并知道它是一个实现MyInterface的对象,仅此而已。
#4
2
The difference is that the second will not compile. You can't instantiate a type parameter with another type parameter with bounds.
不同的是,第二个不会编译。不能用另一个带边界的类型参数实例化一个类型参数。
#5
0
use exact and complete type info in implementations.
在实现中使用准确和完整的类型信息。
ArrayList<MyInterface> mylist = new ArrayList<MyInterface>();
#1
7
Second one won't compile. Imagine:
第二个不会编译。想象一下:
A implements MyInterface
B implements MyInterface
Then the following would match your second expression, but won't compile:
然后下面的语句将匹配您的第二个表达式,但不会编译:
// incorrect
List<A> mylist = new ArrayList<B>();
Correction: Wrong one too:
更正:错误的:
List<? extends MyInterface> mylist = new ArrayList<MyInterface>();
It is right in a sense it does compile, but you cannot add any subclasses of MyInterface to it. Confusing, but correct -- after I read the explanation. Same reason: wildcard can be viewed for example as:
从某种意义上说,它确实可以编译,但是不能向它添加任何MyInterface的子类。困惑,但正确——在我读了解释之后。同样的原因:可以查看通配符,例如:
// I know this is not compileable; this is internal compiler "thinking".
// Read it as "somewhere someone may instantiate an ArrayList<A> and pass
// it down to us; but we cannot accept it as something that could be
// potentially used as List<B>"
List<A> mylist = new ArrayList<MyInterface>();
So this won't work:
这是行不通的:
mylist.add(b);
and vice versa. Compiler refuses to do those potentially incorrect operations.
反之亦然。编译器拒绝执行那些潜在的错误操作。
The option which allows you to add any subclass of MyInterface to mylist is:
可以添加MyInterface myto mylist任何子类的选项是:
List<MyInterface> mylist = new ArrayList<MyInterface>();
#2
4
If you would like to store the ojects of type MyInterface
the better (and compilable) approach would be -
如果您想存储MyInterface类型的对象,更好的(和可编译的)方法是-
List<MyInterface> mylist = new ArrayList<MyInterface>();
But if you would like to use in the method parameter then you can use option 2 (bounded wildcard type) for API flexibility.
但是如果您想在方法参数中使用,那么您可以使用选项2(有界通配符类型)来实现API的灵活性。
public void someMethod(List<? extends MyInterface> myInterfaces);
EDIT:
The above code will give the more flexibility API because Generic types are invariant, so if you have -
编辑:上面的代码将提供更灵活的API,因为泛型类型是不变的,所以如果您有-
public class A implements MyInterface {
// some implementation
}
and if someMethod
has a parameter type List<MyInterface>
then it won't be able to take the List<A>
, this forces API users to create List
with type MyInterface
on the other side - List<? extends MyInterface>
will allow to pass List<A>
to someMethod
.. client usually has a List<ActualObject>
so it's more flexible to provide a parameter which will take any implementation of MyInterface
At the same time do not use wildcard types as return types like
如果someMethod有一个参数类型列表
public List<? extends MyInterface> someMethod();
If the user of a class has to think about wildcard types, there is probably something wrong with the class’s API.
如果一个类的用户必须考虑通配符类型,那么这个类的API可能有问题。
#3
4
List<? extends MyInterface>
means a list of some subtype of MyInterface
, but we don't know which subtype.
列表< ?扩展MyInterface>表示MyInterface的某个子类型的列表,但是我们不知道是哪个子类型。
Since we don't know which subtype is used actually, we can't put any object in it (as we can't ensure that it is an element of this subtype).
因为我们不知道实际使用的是哪个子类型,所以我们不能在其中放入任何对象(因为我们不能确保它是该子类型的元素)。
We can take objects out of such a list, and know that it is an object implementing MyInterface
, but nothing more.
我们可以从这样的列表中取出对象,并知道它是一个实现MyInterface的对象,仅此而已。
#4
2
The difference is that the second will not compile. You can't instantiate a type parameter with another type parameter with bounds.
不同的是,第二个不会编译。不能用另一个带边界的类型参数实例化一个类型参数。
#5
0
use exact and complete type info in implementations.
在实现中使用准确和完整的类型信息。
ArrayList<MyInterface> mylist = new ArrayList<MyInterface>();