The Pain of Java 8 Lambda
I was recently doing performance optimization for booster-task-analyser and found myself missing Java. So I tried writing something in Java again, but it felt painful – especially try-catch inside lambda expressions. What should be a one-liner bloats into six lines. (This is exactly how productivity dies.) I started wondering: can we make Java 8 lambdas less miserable?
Unchecked Exception
In Java, only two types of Throwable don’t require a try-catch:
RuntimeException
The Java designers considered RuntimeException to be the programmer’s fault, so catching it isn’t mandatory.
Error
The Java designers considered Error to be the most severe kind of exception – typically unrecoverable with no way to handle it. Catching it wouldn’t help.
Based on this reasoning, can we make lambdas throw RuntimeException whenever a checked exception would otherwise need catching?
As it happens, Java 8 introduced UncheckedIOException in the JDK specifically to make Lambda usage more convenient in the Stream API. For example:
1 | public class BufferedReader extends Reader { |
While UncheckedIOException solves the problem, it still feels clunky. So I wondered: can we make this more concise?
Rolling Our Own
Consider this code:
1 | public void cat(Collection<File> files) { |
Wouldn’t it be nice to write it like this instead (even with a minor difference)?
1 | public void cat(Collection<File> files) { |
What if we wrap the lambda in another layer? Something like this would work:
1 | public void cat(Collection<File> files) { |
A few extra parentheses, sure, but much cleaner than the original. So how do we make this wrapper work for all cases?
Methods with Return Values
Since Java 8 supports Functional Interfaces, methods with return values can be defined as:
1 |
|
Then wrap the lambda with this method:
1 | public static <R, E extends Throwable> R unchecked(final Procedure<R, E> procedure) { |
Methods without Return Values
Methods without return values can be defined as:
1 |
|
Then wrap the lambda with this method:
1 | public static <E extends Throwable> void unchecked(final Block<? super E> block) { |
OK, done! Not a bad little wheel to reinvent.
Verbose Variable Declarations
After getting used to Kotlin, going back to Java makes everything feel verbose. So I thought: can we shorten Java‘s variable declarations too? Thinking of jQuery‘s $() pattern in JavaScript, and since $ is a legal identifier in Java, let’s build another utility:
1 | public static <T> void $(final T object, final Consumer<? super T> consumer) { |
Now in the Java world, we can play like JavaScript:
1 | $(new File("..."), (f) -> { |
If you’re interested in this little utility, check it out here: lambda-support
- Blog Link: https://johnsonlee.io/2020/04/15/the-pain-of-java-8-lambda.en/
- Copyright Declaration: 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
