Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
196 views
in Technique[技术] by (71.8m points)

Java 8: Mandatory checked exceptions handling in lambda expressions. Why mandatory, not optional?

I'm playing with the new lambda features in Java 8, and found that the practices offered by Java 8 are really useful. However, I'm wondering is there a good way to make a work-around for the following scenario. Suppose you have an object pool wrapper that requires some kind of a factory to fill the object pool, for example (using java.lang.functions.Factory):

public class JdbcConnectionPool extends ObjectPool<Connection> {

    public ConnectionPool(int maxConnections, String url) {
        super(new Factory<Connection>() {
            @Override
            public Connection make() {
                try {
                    return DriverManager.getConnection(url);
                } catch ( SQLException ex ) {
                    throw new RuntimeException(ex);
                }
            }
        }, maxConnections);
    }

}

After transforming the functional interface into lambda expression, the code above becomes like that:

public class JdbcConnectionPool extends ObjectPool<Connection> {

    public ConnectionPool(int maxConnections, String url) {
        super(() -> {
            try {
                return DriverManager.getConnection(url);
            } catch ( SQLException ex ) {
                throw new RuntimeException(ex);
            }
        }, maxConnections);
    }

}

Not so bad indeed, but the checked exception java.sql.SQLException requires a try/catch block inside the lambda. At my company we use two interfaces for long time:

  • IOut<T> that is an equivalent to java.lang.functions.Factory;
  • and a special interface for the cases that usually require checked exceptions propagation: interface IUnsafeOut<T, E extends Throwable> { T out() throws E; }.

Both IOut<T> and IUnsafeOut<T> are supposed to be removed during migration to Java 8, however there is no exact match for IUnsafeOut<T, E>. If the lambda expressions could deal with checked exceptions like they were unchecked, it could be possible to use simply like the following in the constructor above:

super(() -> DriverManager.getConnection(url), maxConnections);

That looks much cleaner. I see that I can rewrite the ObjectPool super class to accept our IUnsafeOut<T>, but as far as I know, Java 8 is not finished yet, so could be there some changes like:

  • implementing something similar to IUnsafeOut<T, E>? (to be honest, I consider that dirty - the subject must choose what to accept: either Factory or "unsafe factory" that cannot have compatible method signatures)
  • simply ignoring checked exceptions in lambdas, so no need in IUnsafeOut<T, E> surrogates? (why not? e.g. another important change: OpenJDK, that I use, javac now does not require variables and parameters to be declared as final to be captured in an anonymous class [functional interface] or lambda expression)

So the question is generally is: is there a way to bypass checked exceptions in lambdas or is it planned in the future until Java 8 is finally released?


Update 1

Hm-m-m, as far as I understand what we currently have, it seems there is no way at the moment, despite the referenced article is dated from 2010: Brian Goetz explains exception transparency in Java. If nothing changed much in Java 8, this could be considered an answer. Also Brian says that interface ExceptionalCallable<V, E extends Exception> (what I mentioned as IUnsafeOut<T, E extends Throwable> out of our code legacy) is pretty much useless, and I agree with him.

Do I still miss something else?

Question&Answers:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Not sure I really answer your question, but couldn't you simply use something like that?

public final class SupplierUtils {
    private SupplierUtils() {
    }

    public static <T> Supplier<T> wrap(Callable<T> callable) {
        return () -> {
            try {
                return callable.call();
            }
            catch (RuntimeException e) {
                throw e;
            }
            catch (Exception e) {
                throw new RuntimeException(e);
            }
        };
    }
}

public class JdbcConnectionPool extends ObjectPool<Connection> {

    public JdbcConnectionPool(int maxConnections, String url) {
        super(SupplierUtils.wrap(() -> DriverManager.getConnection(url)), maxConnections);
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...