This article is participating in the Java Theme Month – Java Debug Notes Event, see the event link for details

Lambdas fail to derive generics in jdK8, resulting in compile-time errors

Error:(24, 29) Java: an unreported exception Error java.lang.throwable; It must be caught or declared for throwing

Let’s take a look

Scenario simulation

The following code

import java.util.Optional;

public class B {
    public static void main(String[] args) {
        String s=null;
        Optional.ofNullable(s).orElseThrow(() -> {
            throw new RuntimeException(""); }); }}Copy the code

run

This error will be thrown directly when running with IDEA.

I did a bit of Internet research and saw that someone was blaming the compiler and saying Eclipse doesn’t (really…).

So I half-heartedly tried manual compilation, but it didn’t work either.

JDK8bug?

I found this later on Stack Overflow

Throw RuntimeException inside Stream with Optional.orElseThrow

This is a BUG in the JDK, you can click on the link below to see 😝

This is a compiler bug JDK-8047338 which prevent correct generic exception type inference. It was partially resolved in 1.8.0 comes with _92 release

As follows:

So I looked at the local JDK version and it was 271.. Also not line.

I simply switched the JDK to version 11, and it compiled and ran!

So how do you keep your code running without updating the JDK?

The solution

Start with the source code

Here is Optional’s orElseThrow source code

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X { 
    if(value ! =null) {
        return value;
    } else {
        throwexceptionSupplier.get(); }}Copy the code

You can see that this is a generic method, so follow the error message and try adding the generic exception ~

The program worked

4 ye also find here a big talking this bug, see zhuanlan.zhihu.com/p/111643471

And from StackOverflow,

Java 8 generics + exceptions compile time error when using a lambda expression

You can see that this is also done manually by adding the exception message ~

Interested friends remember to take a look ~

Remember, remember (° °) Blue ✿

The generic

Finally, a brief review of some generic writing ~, do not forget the characteristics of generics

Characteristics of generics:

  1. Compile the erase
  2. Type safety
  3. Eliminate casts

A generic class

class Fruit<T> {}

A generic interface

interface IAnimal<T>{}

Generic variables

T a;

Generic method

T getAnimal();

The wildcard

List<? >

Generics upper and lower bounds:PECS(Producer Extends Consumer Super)

Upper limit of the generic

? Extend T belongs to Producer Extends and can get values but cannot modify them.

Such as: the List
indicates that only get methods can be called, not add

Generic floor

? Super T is a Consumer super that can be modified but not retrieved.

Such as: the List
indicates that only add methods can be called, not get methods

Conclusion:

  1. JDK8 failed to use lambdas to derive the type of a generic, manually specifying the type can fix the problem!
  2. You can upgradeJDKTo solve this problem
  3. If you want to get into this a little bit morelambdaYou can study itjava.lang.invoke.LambdaMetafactory

I am 4ye, we will see you next time, ヾ( ̄▽ ̄)Bye Bye