1 回答

TA贡献1788条经验 获得超4个赞
有一些方法。
使用“围绕执行”成语。重新制定接口以简化客户端实现并消除问题。
忽略问题。听起来很愚蠢,但这通常是使用 I/O 流装饰器包装时发生的情况。
包装在代理中,并将其放在试用资源中。
AutoCloseable
写出与资源一起尝试使用尝试捕获和尝试最终的等效项。(我不会 - 讨厌。
将修改后的试用资源编写为库功能。此代码将成为执行周围的客户端。
编写异常处理旧学校风格与尝试捕捉和尝试最终。
编辑:我想我会重新审视答案,添加一些示例代码来娱乐。
围绕成语执行
简单而最好的解决方案。不幸的是,Java库并不经常使用它(这是一个很大的例外),并且约定也没有很好地建立。与以往一样,Java在没有支持功能的情况下检查的异常使事情变得棘手。我们不能使用,必须发明我们自己的功能接口。AccessController.doPrivileged
java.util.function
// Like Consumer, but with an exception.
interface Use<R, EXC extends Exception> {
void use(R resource) throws EXC;
}
public static void withThing(String name, Use<InputStream,IOException> use) throws IOException {
try (InputStream in = new FileInputStream(name)) {
use.use(in);
}
}
很好,很简单。无需担心客户端代码会弄乱资源处理,因为它不会这样做。好。
修改后的“使用资源试用”作为库功能,作为代理实现,可在“使用资源试用”中自动关闭
它会变得丑陋。我们需要将获取、发布和初始化作为 lambdas 传递。直接在此方法中创建资源将打开一个小窗口,其中意外的异常会导致泄漏。
public static InputStream newThing(String name) throws IOException {
return returnResource(
() -> new FileInputStream(name),
InputStream::close,
in -> {
int ignore = in.read(); // some work
}
);
}
的一般实现将类似于下面的这个黑客。这是一个黑客,因为尝试资源不支持这种事情,Java库不支持检查异常。请注意,限制为一个例外(对于未选中的例外,可以使用未选中的例外)。returnResource
interface Acquire<R, EXC extends Exception> {
R acquire() throws EXC;
}
// Effectively the same as Use, but different.
interface Release<R, EXC extends Exception> {
void release(R resource) throws EXC;
}
public static <R, EXC extends Exception> R returnResource(
Acquire<R, EXC> acquire, Release<R, EXC> release, Use<R, EXC> initialize
) throws EXC {
try (var adapter = new AutoCloseable() { // anonymous classes still define type
private R resource = acquire.acquire();
R get() {
return resource;
}
void success() {
resource = null;;
}
public void close() throws EXC {
if (resource != null) {
release.release(resource);
}
}
}) {
R resource = adapter.get();
initialize.use(resource);
adapter.success();
return resource;
}
}
如果我们将构建资源的参数与资源的构造分开,这可能会更干净。
public static InputStream newThing(String name) throws IOException {
return returnResource(
name,
FileInputStream::new,
InputStream::close,
in -> {
int ignore = in.read(); // some work
}
);
}
// Like Function, but with a more descriptive name for a functional interface.
interface AcquireFrom<T, R, EXC extends Exception> {
R acquire(T t) throws EXC;
}
public static <T, R, EXC extends Exception> R returnResource(
T t, AcquireFrom<T, R, EXC> acquire, Release<R, EXC> release, Use<R, EXC> initialize
) throws EXC {
return returnResource(() -> acquire.acquire(t), release, initialize);
}
因此,总而言之,以下事情是痛苦的:
转让资源所有权。将其保留在本地。
java.util.function
不支持选中的异常。Java 库不支持执行周围。
AutoCloseable::close
声明它抛出而不是成为类型的类型参数。Exception
已检查没有总和类型的异常。
一般的 Java 语言语法。
添加回答
举报