Java 8 option list collection list compilation error

I can't understand the difference

Stream<Optional<Integer>> optionalStream = Stream.of(
                Optional.of(1),Optional.empty(),Optional.of(5));

List<Optional<Integer>> optionalList = optionalStream.collect(Collectors.toList());

Which works well and:

List<Optional<Integer>> optionalList1 = Stream.of(
                Optional.of(1),Optional.of(5)).collect(Collectors.toList());

I got the wrong place

Error:(138,40) java: incompatible types: inference variable T has incompatible bounds
    equality constraints: java.util.Optional<java.lang.Integer>
    lower bounds: java.util.Optional<? extends java.lang.Object>

Solution

I've reduced some examples and tried to compile with - xdverboseresolution = all to output information about type inference:

final class One {
  void one() {
    Stream<Optional<Integer>> optionalStream = Stream.of(Optional.empty());
    List<Optional<Integer>> optionalList = optionalStream.collect(Collectors.toList());
  }
}

final class Two {
  void two() {
    List<Optional<Integer>> optionalList1 =
        Stream.of(Optional.empty()).collect(Collectors.toList());
  }
}

In the case of two, it looks like stream The delayed instantiation of of is completed even before viewing subsequent Collections:

...
Two.java:9: Note: Deferred instantiation of method <T>of(T)
        Stream.of(Optional.empty()).collect(Collectors.toList());
                 ^
  instantiated signature: (Optional<Object>)Stream<Optional<Object>>
  target-type: <none>
  where T is a type-variable:
    T extends Object declared in method <T>of(T)
Two.java:9: Note: resolving method collect in type Stream to candidate 0
        Stream.of(Optional.empty()).collect(Collectors.toList());
...

(the "solution collection" is the first mention of collection)

There is no target type to constrain it; The instantiated signature shows that it is stream < optional < Object > >

If you look at a corresponding output:

...
One.java:8: Note: Deferred instantiation of method <T>of(T)
    Stream<Optional<Integer>> optionalStream = Stream.of(Optional.empty());
                                                        ^
  instantiated signature: (Optional<Integer>)Stream<Optional<Integer>>
  target-type: Stream<Optional<Integer>>
  where T is a type-variable:
    T extends Object declared in method <T>of(T)
...

It is correct because it knows the target type

I can't say exactly why deferred instantiation occurs at 2 at this time, because I'm not familiar with the way type inference is applied

I think it's because of stream The call to of is not considered a poly expression, but I can't really convince myself why (see some incoherent ramblings in editing history)

My suggested fix is to apply type hints to optional Empty(), i.e. optional< Integer> empty(). This has the effect of getting the actual type of the optional item earlier in reasoning, so the event is known when delaying instantiation, although the target type is still unknown:

final class Three {
  void three() {
    List<Optional<Integer>> optionalList1 =
        Stream.of(Optional.<Integer>empty()).collect(Collectors.toList());
  }
}

...
Three.java:9: Note: resolving method of in type Stream to candidate 1
        Stream.of(Optional.<Integer>empty()).collect(Collectors.toList());
              ^
  phase: BASIC
  with actuals: Optional<Integer>
  with type-args: no arguments
  candidates:
      #0 not applicable method found: <T#1>of(T#1...)
        (cannot infer type-variable(s) T#1
          (argument mismatch; Optional<Integer> cannot be converted to T#1[]))
      #1 applicable method found: <T#2>of(T#2)
        (partially instantiated to: (Optional<Integer>)Stream<Optional<Integer>>)
  where T#1,T#2 are type-variables:
    T#1 extends Object declared in method <T#1>of(T#1...)
    T#2 extends Object declared in method <T#2>of(T#2)
Three.java:9: Note: Deferred instantiation of method <T>of(T)
        Stream.of(Optional.<Integer>empty()).collect(Collectors.toList());
                 ^
  instantiated signature: (Optional<Integer>)Stream<Optional<Integer>>
  target-type: <none>
  where T is a type-variable:
    T extends Object declared in method <T>of(T)
...
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>