我正在使用Java 8中的新lambda特性,并发现Java 8提供的实践非常有用。然而,我正在考虑是否有一种好的方法来解决以下情况。假设您有一个对象池包装器,需要某种工厂来填充对象池,例如(使用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);
}
}
将函数式接口转换为lambda表达式后,上面的代码会变成这样:
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);
}
}
确实不错,但是检查异常
java.sql.SQLException
需要在lambda内部使用try
/catch
块。在我们公司,长期以来我们使用两个接口:
IOut<T>
相当于java.lang.functions.Factory
;- 对于通常需要传播已检查异常的情况,有一个特殊的接口:
interface IUnsafeOut<T, E extends Throwable> { T out() throws E; }
。
IOut<T>
和IUnsafeOut<T>
都应该在迁移到Java 8时删除,但是IUnsafeOut<T, E>
没有完全匹配项。如果lambda表达式可以像未经检查的异常一样处理已检查的异常,就可以在上面的构造函数中简单地使用以下内容:super(() -> DriverManager.getConnection(url), maxConnections);
看起来更加清晰了。我发现我可以重写ObjectPool
超类以接受我们的IUnsafeOut<T>
,但据我所知,Java 8尚未完成,因此可能会有一些更改,例如:
- 实现类似于
IUnsafeOut<T, E>
的东西?(说实话,我认为这很糟糕 - 主题必须选择接受什么:要么是Factory
,要么是无法具有兼容方法签名的“不安全工厂”) - 在lambda中简单地忽略已检查的异常,因此不需要
IUnsafeOut<T, E>
替代品?(为什么不呢?例如,另一个重要的变化:我使用的OpenJDK的javac
现在不需要将变量和参数声明为final
即可在匿名类[函数接口]或lambda表达式中捕获)
因此,问题通常是:是否有办法绕过lambda中的已检查异常,或者计划在Java 8最终发布之前在将来解决这个问题?
更新1
嗯,就我目前所了解的情况而言,似乎目前没有办法,尽管引用的文章是从2010年起的:Brian Goetz解释了Java中的异常透明度。如果在Java 8中没有太多变化,这可以被视为一个答案。此外,Brian表示interface ExceptionalCallable<V, E extends Exception>
(我在我们的代码遗留中提到的IUnsafeOut<T, E extends Throwable>
)几乎没用,我同意他的观点。
我还错过了其他什么吗?