This question already has an answer here:
这个问题在这里已有答案:
- Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic? 16 answers
List
I may be having it wrong but i am getting an error with an Optional<>
as method argument in Java.
我可能错了,但我在Java中使用Optional <>作为方法参数时出错。
I have an interface:
我有一个界面:
public interface FooInterface;
And a class that implements it
还有一个实现它的类
public class Foo implements FooInterface;
Now, suppose i have a method that receives an Optional<FooInterface>
现在,假设我有一个接收Optional
someMethod(Optional<FooInterface> arg)
I get an error if i do this:
如果我这样做,我会收到错误:
Optional<Foo> foo = Optional.of(new Foo());
someMethod(foo);
It says that Optional<FooInterface>
is expected instead of Optional<Foo>
.
它说可选
Why is that?
这是为什么?
3 个解决方案
#1
1
-
Use the interface type
FooInterface
:使用接口类型FooInterface:
final FooInterface foo = new Foo(); final Optional<FooInterface> optional = Optional.of(foo);
-
Correct the argument type to
Optional<? extends FooInterface>
. It'll allow passing anOptional<AnyFooInterfaceSubclass>
.将参数类型更正为Optional 。它将允许传递Optional
。 -
Try not using the
Optional
for parameters and fields.请勿尝试使用Optional参数和字段。
#2
1
That is a general drawback of generic types involving extends/implements
.
这是涉及扩展/实现的泛型类型的一般缺点。
interface Ifc { }
class Cls implements Ifc { }
void somemethod2(List<Ifc> arg) { }
List<Cls> list = new UnlinkedList<>();
somemethod2(list); // COMPILE ERROR
In your case a solution would be:
在您的情况下,解决方案将是:
somemethod(Optional<FooInterface>.of(foo));
Or declare
void someMethod(Optional<? extends FooInterface> arg) {
Fortunately Optional is immutable, but for List this would be problematically, as you could not set an element with Foo, as it could have been a List of an other FooInterface implementing class. So maybe better to avoid.
幸运的是,Optional是不可变的,但是对于List,这将是有问题的,因为你不能用Foo设置一个元素,因为它可能是另一个FooInterface实现类的List。所以最好避免。
There exist some proponents of avoiding Optional parameters, in favor of doing only work on non-optional objects. I do not see that as such. IMHO there are many valid uses of Optional parameters.
存在一些避免可选参数的支持者,支持仅对非可选对象进行操作。我不这么认为。恕我直言,可选参数有许多有效用途。
#3
0
This has nothing to do with Optional
itself, it applies to any generic type.
这与Optional本身无关,它适用于任何泛型类型。
Java generics are invariant, which means Collection<Foo>
(or Optional
, or whatever) is not a subtype of Collection<FooInterface>
, even though Foo
itself is a subtype of FooInterface
.
Java泛型是不变的,这意味着Collection
You need to make that generic type covariant using a wildcard (as @Henrik pointed out already):
您需要使用通配符来创建该泛型类型协变(如@Henrik已经指出的那样):
/**
* accepts an optional value of type `FooInterface` or any subtype
*/
someMethod(Optional<? extends FooInterface> arg);
#1
1
-
Use the interface type
FooInterface
:使用接口类型FooInterface:
final FooInterface foo = new Foo(); final Optional<FooInterface> optional = Optional.of(foo);
-
Correct the argument type to
Optional<? extends FooInterface>
. It'll allow passing anOptional<AnyFooInterfaceSubclass>
.将参数类型更正为Optional 。它将允许传递Optional
。 -
Try not using the
Optional
for parameters and fields.请勿尝试使用Optional参数和字段。
#2
1
That is a general drawback of generic types involving extends/implements
.
这是涉及扩展/实现的泛型类型的一般缺点。
interface Ifc { }
class Cls implements Ifc { }
void somemethod2(List<Ifc> arg) { }
List<Cls> list = new UnlinkedList<>();
somemethod2(list); // COMPILE ERROR
In your case a solution would be:
在您的情况下,解决方案将是:
somemethod(Optional<FooInterface>.of(foo));
Or declare
void someMethod(Optional<? extends FooInterface> arg) {
Fortunately Optional is immutable, but for List this would be problematically, as you could not set an element with Foo, as it could have been a List of an other FooInterface implementing class. So maybe better to avoid.
幸运的是,Optional是不可变的,但是对于List,这将是有问题的,因为你不能用Foo设置一个元素,因为它可能是另一个FooInterface实现类的List。所以最好避免。
There exist some proponents of avoiding Optional parameters, in favor of doing only work on non-optional objects. I do not see that as such. IMHO there are many valid uses of Optional parameters.
存在一些避免可选参数的支持者,支持仅对非可选对象进行操作。我不这么认为。恕我直言,可选参数有许多有效用途。
#3
0
This has nothing to do with Optional
itself, it applies to any generic type.
这与Optional本身无关,它适用于任何泛型类型。
Java generics are invariant, which means Collection<Foo>
(or Optional
, or whatever) is not a subtype of Collection<FooInterface>
, even though Foo
itself is a subtype of FooInterface
.
Java泛型是不变的,这意味着Collection
You need to make that generic type covariant using a wildcard (as @Henrik pointed out already):
您需要使用通配符来创建该泛型类型协变(如@Henrik已经指出的那样):
/**
* accepts an optional value of type `FooInterface` or any subtype
*/
someMethod(Optional<? extends FooInterface> arg);