Issue
The code compiles fine with JDK 8 (1.8.0_212) but fails to compile using JDK 11 (11.0.3) both Oracle jdk and open jdk (aws corretto)
Tried compiling using javac and with Maven (maven version 3.6.1 and maven-compiler-plugin version 3.8.0) it compiles for JDK 8 and fails for JDK 11.
import java.net.URL;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.function.Function;
import java.util.stream.Stream;
public class AppDemo {
public static void main(String[] args) {
// NO error here
giveMeStream("http://foo.com").map(wrap(url -> new URL(url)));
List<String> list = new ArrayList<String>();
list.add("http://foo.com/, http://bar.com/");
// error: unreported exception MalformedURLException;
// must be caught or declared to be thrown
list.stream().flatMap(
urls -> Arrays.<String>stream(urls.split(",")).map(wrap(url -> new URL(url)))
);
// error: unreported exception MalformedURLException;
// must be caught or declared to be thrown
Stream.concat(
giveMeStream("http://foo.com").map(wrap(url -> new URL(url))),
giveMeStream("http://bar.com").map(wrap(url -> new URL(url))));
}
static Stream<String> giveMeStream(String s) {
return Arrays.stream(new String[]{s});
}
static <T, R, E extends Throwable> Function<T, R>
wrap(FunException<T, R, E> fn) {
return t -> {
try {
return fn.apply(t);
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
};
}
interface FunException<T, R, E extends Throwable> {
R apply(T t) throws E;
}
}
Error:
Expected : No compilation error
Actual : compilation error for JDK11
Error message with JDK 11:
s.<String>stream(urls.split(",")).map(wrap(url -> new URL(url)))
^
AppDemo.java:24: error: unreported exception MalformedURLException; must be caught or declared to be thrown
giveMeStream("http://foo.com").map(wrap(url -> new URL(url))),
^
AppDemo.java:25: error: unreported exception MalformedURLException; must be caught or declared to be thrown
giveMeStream("http://bar.com").map(wrap(url -> new URL(url))));
^
3 errors
Solution
Because slight updates to the spec say so, probably. Does it matter? It's not going to work like this.
There is no real purpose to turning the exception thrown into a parameterized type here. Also, youll make quite the chain of RuntimeException
with this code. Try this, instead:
static <T, R> Function<T, R> wrap(FunException<T, R> fn) {
return t -> {
try {
return fn.apply(t);
} catch (Error | RuntimeException ex) {
throw ex;
} catch (Throwable throwable) {
throw new RuntimeException("Checked exception in lambda", throwable);
}
};
}
interface FunException<T, R> {
R apply(T t) throws Throwable;
}
and now it'll compile fine.
TO THE READER: Don't do this. The correct way to deal with java's rules such as checked exceptions is to deal with them. Using hacks to get around the essence of a language just means your code is non-idiomatic (others who read your code won't get it, and you'll have a hard time reading the code of others. That's bad), tends to interop with other libraries in a bad way, and various features that are supposed to help, now hurt (example: Here you get a LOT of causal exception chains which make the reading of your logs and exception traces more difficult than is needed). Also, being 'off the beaten path' this far leads to fun times such as code that used to compile no longer compiling.
Answered By - rzwitserloot
Answer Checked By - Mildred Charles (JavaFixing Admin)