Lyu*_*riv 69 java lambda checked-exceptions java-8
我正在使用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);
}
}
Run Code Online (Sandbox Code Playgroud)
将函数接口转换为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);
}
}
Run Code Online (Sandbox Code Playgroud)
确实不是那么糟糕,但是经过检查的异常java.sql.SQLException
需要在lambda中使用try
/ catch
block.在我公司,我们长时间使用两个接口:
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);
Run Code Online (Sandbox Code Playgroud)
看起来更干净.我看到我可以重写ObjectPool
超类接受我们的IUnsafeOut<T>
,但据我所知,Java 8尚未完成,所以可能会有一些变化,如:
IUnsafeOut<T, E>
?(老实说,我认为这很脏 - 主题必须选择接受:或者是Factory
"不安全的工厂",不能有兼容的方法签名)IUnsafeOut<T, E>
代理中不需要吗?(为什么不呢?例如,另一个重要的变化:我使用的OpenJDK,javac
现在不要求将变量和参数声明为final
在匿名类[功能接口]或lambda表达式中捕获)所以问题通常是:有没有办法绕过lambda中的已检查异常,或者计划将来在Java 8最终发布之前进行计划?
更新1
嗯-mm,据我所知,我们目前所拥有的,目前似乎没有办法,尽管参考文章的日期是2010年:Brian Goetz解释了Java中的异常透明度.如果在Java 8中没有什么变化,这可以被认为是一个答案.Brian也说interface ExceptionalCallable<V, E extends Exception>
(我在IUnsafeOut<T, E extends Throwable>
代码遗产中提到的内容)几乎没用,我同意他的看法.
我还想念别的吗?
JB *_*zet 43
不确定我真的回答你的问题,但你不能简单地使用这样的东西吗?
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);
}
}
Run Code Online (Sandbox Code Playgroud)
Edw*_*rzo 34
在lambda邮件列表中,这是经过深入讨论的.正如你所看到的那样,Brian Goetz建议选择编写自己的组合器:
或者你可以写自己的琐碎组合:
Run Code Online (Sandbox Code Playgroud)static<T> Supplier<T> exceptionWrappingSupplier(Supplier<T> b) { return e -> { try { b.accept(e); } catch (Exception e) { throw new RuntimeException(e); } }; }
您可以编写一次,而不是写入原始电子邮件所花费的时间.同样适用于您使用的每种SAM.
我宁愿把它看作"玻璃99%满"而不是替代品.并非所有问题都需要新的语言功能作为解决方 (更不用说新语言功能总会导致新问题.)
在那些日子里,Consumer界面被称为Block.
我认为这符合JB Nizet的答案.
后来Brian 解释了为什么这是这样设计的(问题的原因)
是的,您必须提供自己的特殊SAM.但是lambda转换对它们来说可以正常工作.
EG讨论了这个问题的附加语言和库支持,最后认为这是一个糟糕的成本/收益权衡.
基于库的解决方案导致SAM类型爆炸2倍(异常与非异常),与原始专业化的现有组合爆炸相互作用很严重.
可用的基于语言的解决方案是复杂性/价值权衡的输家.虽然有一些替代解决方案我们将继续探索 - 虽然显然不是8,也可能不是9.
在此期间,您可以使用工具来执行您想要的操作.我得到你喜欢我们提供最后一英里你(和,其次,你的要求是真正的"你为什么不干脆放弃对检查的异常已经是"一个自动精简含蓄的要求),但我认为目前的状态让你完成了你的工作.
2015年9月:
你可以使用ET.ET是一个用于异常转换/转换的小型Java 8库.
使用ET,您可以写:
super(() -> et.withReturningTranslation(() -> DriverManager.getConnection(url)), maxConnections);
Run Code Online (Sandbox Code Playgroud)
多行版本:
super(() -> {
return et.withReturningTranslation(() -> DriverManager.getConnection(url));
}, maxConnections);
Run Code Online (Sandbox Code Playgroud)
您之前需要做的就是创建一个新的 ExceptionTranslator
实例:
ExceptionTranslator et = ET.newConfiguration().done();
Run Code Online (Sandbox Code Playgroud)
此实例是线程安全的,可由多个组件共享.FooCheckedException -> BarRuntimeException
如果您愿意,可以配置更具体的异常转换规则(例如).如果没有其他规则可用,则已检查的异常会自动转换为RuntimeException
.
(免责声明:我是ET的作者)
我们在公司开发了一个内部项目来帮助我们解决这个问题。两个月前我们决定上市。
这就是我们想到的:
@FunctionalInterface
public interface ThrowingFunction<T,R,E extends Throwable> {
R apply(T arg) throws E;
/**
* @param <T> type
* @param <E> checked exception
* @return a function that accepts one argument and returns it as a value.
*/
static <T, E extends Exception> ThrowingFunction<T, T, E> identity() {
return t -> t;
}
/**
* @return a Function that returns the result of the given function as an Optional instance.
* In case of a failure, empty Optional is returned
*/
static <T, R, E extends Exception> Function<T, Optional<R>> lifted(ThrowingFunction<T, R, E> f) {
Objects.requireNonNull(f);
return f.lift();
}
static <T, R, E extends Exception> Function<T, R> unchecked(ThrowingFunction<T, R, E> f) {
Objects.requireNonNull(f);
return f.uncheck();
}
default <V> ThrowingFunction<V, R, E> compose(final ThrowingFunction<? super V, ? extends T, E> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> ThrowingFunction<T, V, E> andThen(final ThrowingFunction<? super R, ? extends V, E> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
/**
* @return a Function that returns the result as an Optional instance. In case of a failure, empty Optional is
* returned
*/
default Function<T, Optional<R>> lift() {
return t -> {
try {
return Optional.of(apply(t));
} catch (Throwable e) {
return Optional.empty();
}
};
}
/**
* @return a new Function instance which wraps thrown checked exception instance into a RuntimeException
*/
default Function<T, R> uncheck() {
return t -> {
try {
return apply(t);
} catch (final Throwable e) {
throw new WrappedException(e);
}
};
}
Run Code Online (Sandbox Code Playgroud)
}
http://github.com/pivovarit/ throwing-function
归档时间: |
|
查看次数: |
42279 次 |
最近记录: |