【问题标题】:try-with-resource without declaring variable在不声明变量的情况下尝试资源
【发布时间】:2022-01-19 15:35:42
【问题描述】:

我想使用 try-with-resource 来切换上下文,但似乎 try() 不能在不声明变量的情况下使用资源,这会使代码不那么优雅。例如

class SwitchContext implements Closeable {
   public SwitchContext(String newContext) {
     //Set new context to local thread
   }

   public void close() {
     //Restore old context to local thread
   }

及用法:

String func() {
  try (new SwitchContext(newContext)) {
     //Do something
     return "dummy";
  }

void func2() {
  try (new SwitchContext(newContext)) {
     //Do something
  }

但我在 try() 上遇到语法错误。只有当我这样写: try (SwitchContext c = new SwitchContext(newContext)) { 它通过了编译。 最优雅的方法是什么?

更新

由于在某些答案中人们不明白我要做什么,我会尝试更好地解释。我正在尝试以更优雅的方式执行以下逻辑:

void func() {
   Context old = ContextUtil.getCurrentContext();
   try() {
       ContextUtil.setContext(A)
       //Do something or call other methods
       //Any method than need the context use ContextUtil.getCurrentContext()
   } finally () {
      ContextUtil.setContext(old)
   }
}

【问题讨论】:

  • 这样做有什么意义?如果你不将它分配给一个变量,你就不能在 try 块中使用它,因此你可能根本不声明它。
  • @OHGODSPIDERS 如果它在其构造函数和 close() 方法中有一些设置和清理,这是 try 块内的代码所必需的。
  • 将其分配给变量似乎是最简单的解决方案。或者也许使用传统的 try/finally 块而不是可关闭的对象会更合适。
  • @khelwood 好吧,我没想到。仍然看起来像一个奇怪的边缘情况,而不是真正的可关闭资源通常用于什么。
  • 想知道:您对得到的答案还有疑问吗?如果没有,并且您的问题已解决,请考虑在某个时候接受其中一个答案。

标签: java try-catch


【解决方案1】:

不要丢弃新对象的引用

new 命令返回对新实例化对象的引用。您的代码尝试将丢弃该引用。因此,您要遵循的任何代码都无法访问该实例化的资源对象。创建一个无法使用的资源对象是没有意义的。

解决方案是创建一个引用变量,我们可以在其中捕获新创建的资源对象的引用。

String func() {
    try (
        SwitchContext context = new SwitchContext( newContext ) ;
    ) {
    // Do something with that resource.
    String result = context.calculate() ;
    return result ;
}
// At this point, `SwitchContext#close` has been called and executed, closing our resource object. 

您评论说,«这不是一个真正的新资源»。如果您的意思是要使用并自动关闭的对象已经实例化,请使用不同形式的 try-with-resources。

在更高版本的 Java 中,您的 try-with-resources 可以访问并自动关闭之前实例化的资源。

SwitchContext context = new SwitchContext( newContext ) ;
… more code …
String func() {
    try (
       context
    ) {
    // Do something with that resource.
    String result = context.calculate() ;
    return result ;
}
// At this point, `SwitchContext#close` has been called and executed, closing our resource object. 

Try-with-resources 就是调用close

请记住,使用 try-with-resources 的全部意义在于让 JVM 自动调用资源的 close 方法。如果您不打算调用 close,请在您的代码中使用不同的控制流结构。

【讨论】:

  • 这不是一个真正的新资源。我只需要一种机制来切换上下文
  • @user3369398 不,调用new 总是 实例化一个新对象。如果实例化不是您的意图,那么您就有设计问题。
  • 你说得对,new 总是创建一个新对象,但我不需要这个引用,因为 close() 并没有真正关闭任何东西,而是将上下文切换回来。所以垃圾收集器可以处理新的引用。查看我的更新以了解我想要做什么。
  • @user3369398 如果你使用 close() 来做其他事情而不是关闭对象使用的资源,那么你就是在滥用它。
【解决方案2】:

try-with-resources 语句是声明一个或多个资源的 try 语句

来自 Oracle tutorial

长话短说:语言的语法就是它。当语言要求声明时,这就是您必须在代码中添加的内容。

或者,如果您想要正式的东西,请查看JLS

TryWithResourcesStatement:
try ResourceSpecification Block [Catches] [Finally]

ResourceSpecification:
( ResourceList [;] )

ResourceList:
Resource {; Resource}

Resource:
LocalVariableDeclaration
VariableAccess
VariableAccess:
ExpressionName
FieldAccess

【讨论】:

    猜你喜欢
    • 2014-06-20
    • 1970-01-01
    • 2023-01-20
    • 2020-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 2021-11-30
    相关资源
    最近更新 更多