【问题标题】:Does Java have a using statement?Java 有 using 语句吗?
【发布时间】:2011-02-25 23:27:52
【问题描述】:

Java 是否有在 hibernate 中打开会话时可以使用的 using 语句?

在 C# 中类似于:

using (var session = new Session())
{


}

所以对象超出范围并自动关闭。

【问题讨论】:

  • "允许为对象定义范围" 这不是 using 所做的。范围不是生命周期(严格来说,using 也与生命周期无关,因为 Dispose 不会破坏对象的内存。)
  • @Joren 您的评论获得了投票,但我可以提供更多信息。您是介绍“终生”概念的人,然后您说这与“终生”无关。范围是 msdn 库中定义中使用的术语,也许我误用了它。你会如何定义using statement
  • Scope 是指代码中的区域,您可以在其中引用标识符而无需使用其完全限定名称(局部变量、类型、方法名称等)。生命周期是指对象或变量可访问的时间。见blogs.msdn.com/b/ericlippert/archive/2009/08/03/…
  • 例如,如果您有一个局部变量并为其分配一个值类型实例,那么您的值的生命周期将在其变量的生命周期结束时结束。但是,如果您分配了一个对象,并将对它的引用存储在本地,那么该对象的生命周期很可能会超过其存储的生命周期,只要在其他地方仍有对该对象的引用。至于using,它会在其作用域的末尾自动dispose对象,但它不会deallocate对象——它的生命周期直到它的所有引用都结束才结束消失了。
  • "using" keyword in java的可能重复

标签: java hibernate using-statement


【解决方案1】:

Java 7 引入了Automatic Resource Block Management,将这一特性带到了 Java 平台。以前的 Java 版本没有类似 using 的东西。

例如,您可以通过以下方式使用实现java.lang.AutoCloseable 的任何变量:

try(ClassImplementingAutoCloseable obj = new ClassImplementingAutoCloseable())
{
    ...
}

Java 的java.io.Closeable 接口由流实现,自动扩展AutoCloseable,因此您已经可以在try 块中使用流,就像在C# using 块中使用它们一样。这相当于 C# 的using

version 5.0, Hibernate Sessions implement AutoCloseable 开始,可以在 ARM 块中自动关闭。在以前版本的 Hibernate Session did not implement AutoCloseable。因此,您需要在 Hibernate >= 5.0 上才能使用此功能。

【讨论】:

  • “幸运的是”Java 7 现在可用,这个答案不再正确(我认为 ARM 块 正是 using 所做的)。
  • @Joachim Sauer:谢谢。我更新了我的答案以反映时间的流逝。就您而言,ARM 块正是 using 的作用;在我写这个答案的时候,在我看来 ARM 块必须是 try 块,而 using 可以应用于任何任意块。现在看,似乎 do 关键字可以在 java 中使用来完成此操作。这是最近添加到提案中的还是我第一次错过了它? OP还专门询问了Hibernate Sessions。 AFAIK:Hibernate Sessions 仍然没有实现AutoCloseable,所以他们还不能使用 ARM。
  • Not event in 4.3 Hibernate DOES NOT 实现 AutoCloseable。 docs.jboss.org/hibernate/orm/4.3/javadocs/index.html?org/…我想每个人都可以编写自己的包装器?
  • Session 无法实现 AutoCloseable,因为 Session.close() 返回一个连接。我认为这是一个糟糕的设计,但我怀疑这会永远改变。
  • @usr-local-ΕΨΗΕΛΩΝ 我只是想如果他们实现了该接口,他们将强制任何使用休眠的人切换到 java 7。 AutoCloseable 在 java 7 之前不存在吗?
【解决方案2】:

在 Java 7 之前,Java 中没有此类功能(对于 Java 7 及更高版本,请参阅 Asaph's answer 关于 ARM)。

您需要手动完成,很痛苦

AwesomeClass hooray = null;
try {
  hooray = new AwesomeClass();
  // Great code
} finally {
  if (hooray!=null) {
    hooray.close();
  }
}

这只是// Great codehooray.close() 都不能抛出任何异常的代码。

如果您真的只想限制变量的范围,那么一个简单的代码块就可以完成这项工作:

{
  AwesomeClass hooray = new AwesomeClass();
  // Great code
}

但这可能不是你的意思。

【讨论】:

  • 如果 // Great code 抛出异常,你的 Java 等价物应该没问题。
  • 当构造函数抛出异常时,我认为你的代码会导致 NullPointerException 掩盖原始异常。
  • @Michael:实际上我的示例无法编译,因为 horray 可能还没有被初始化(现在已修复)。
  • +1 用于浮动简单块能够限制范围。然而,每当我看到这些,它几乎总是表明该方法应该被分解成更小的块。
  • 如果你想从构造函数中捕获任何异常,你必须将它放在 try 块中。将整个东西包装在另一个 try/catch 中会很麻烦。
【解决方案3】:

从 Java 7 开始:http://blogs.oracle.com/darcy/entry/project_coin_updated_arm_spec

问题中代码的语法是:

try (Session session = new Session())
{
  // do stuff
}

请注意,Session 需要实现 AutoClosable 或其(许多)子接口之一。

【讨论】:

    【解决方案4】:

    技术上:

    DisposableObject d = null;
    try {
        d = new DisposableObject(); 
    }
    finally {
        if (d != null) {
            d.Dispose();
        }
    }
    

    【讨论】:

    【解决方案5】:

    最接近的java等价物是

    AwesomeClass hooray = new AwesomeClass();
    try{
        // Great code
    } finally {
        hooray.dispose(); // or .close(), etc.
    }
    

    【讨论】:

      【解决方案6】:

      目前还没有。

      但是,有一个针对 Java 7 的 ARM 提案。

      【讨论】:

        【解决方案7】:

        如果您对资源管理感兴趣,Project Lombok 提供了@Cleanup 注释。直接取自他们的网站:

        您可以使用@Cleanup 来确保给定的 资源被自动清理 在代码执行路径退出之前 您当前的范围。你这样做 注释任何局部变量 用@Cleanup 声明 像这样的注释:

        @Cleanup InputStream in = new FileInputStream("some/file");

        作为一个 结果,在你的范围的末尾 在,in.close() 被调用。这个电话是 保证以一种方式运行 尝试/最终构造。看着那(这 下面的例子来看看它是如何工作的。

        如果您想要的对象类型 清理没有close() 方法,但其他一些无参数 方法,可以指定名称 这个方法是这样的:

        @Cleanup("dispose") org.eclipse.swt.widgets.CoolBar bar = new CoolBar(parent, 0);

        默认情况下,清理方法被假定为 close()。一种清理方法,需要 参数不能通过调用 @Cleanup.

        原版 Java

        import java.io.*;
        
        public class CleanupExample {
          public static void main(String[] args) throws IOException {
            InputStream in = new FileInputStream(args[0]);
            try {
              OutputStream out = new FileOutputStream(args[1]);
              try {
                byte[] b = new byte[10000];
                while (true) {
                  int r = in.read(b);
                  if (r == -1) break;
                  out.write(b, 0, r);
                }
              } finally {
                out.close();
              }
            } finally {
              in.close();
            }
          }
        }
        

        与龙目岛

        import lombok.Cleanup;
        import java.io.*;
        
        public class CleanupExample {
          public static void main(String[] args) throws IOException {
            @Cleanup InputStream in = new FileInputStream(args[0]);
            @Cleanup OutputStream out = new FileOutputStream(args[1]);
            byte[] b = new byte[10000];
            while (true) {
              int r = in.read(b);
              if (r == -1) break;
              out.write(b, 0, r);
            }
          }
        }
        

        【讨论】:

          【解决方案8】:

          不,Java 没有等效的 using 语句。

          【讨论】:

          【解决方案9】:

          在 java 8 中你可以使用 try.请参考下页。 http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

          【讨论】:

            【解决方案10】:

            请看这个List of Java Keywords

            1. 很遗憾,using 关键字不在列表中。
            2. 目前在 Java 中,C# using 关键字与任何其他关键字都不等效。

            要模仿这种"using" 行为,您必须使用try...catch...finally 块,您可以在其中处理finally 中的资源。

            【讨论】:

            • using 不是关键字这一事实并不意味着什么。正如@BalusC 所提到的,可以(并且将会!)使用另一个关键字来实现相同的功能。
            • 我同意!但现在,它不存在,对吧?这就是OP所问的,如果刚才有类似的东西。很高兴知道它将存在于未来的版本中,但这并不会像现在这样或那样改变任何事情。无论如何,@BalusC 提供的信息很棒! =)
            • 我同意这一点,但您的帖子似乎说using 不在 Java 关键字列表中,这意味着 Java 语言中不存在此功能。这不是真的。
            • 如果我的帖子似乎是这样说的,那么我将进行编辑以反映我的意图。
            • 我编辑了我的答案,指定没有 using 关键字,也没有任何等价的现在。谢谢@Joachim Sauer! =)
            【解决方案11】:

            ARM blocks,来自project coin 将在 Java 7 中使用。此功能旨在使用语法为 Java 带来与 .Net 类似的功能。

            【讨论】:

              【解决方案12】:

              回答有关限制变量范围的问题,而不是谈论自动关闭/处置变量。

              在 Java 中,您可以使用大括号定义封闭的匿名范围。非常简单。

              {
                 AwesomeClass hooray = new AwesomeClass()
                 // Great code
              }
              

              变量hooray只能在这个范围内使用,不能在它之外使用。

              如果您有只是临时的重复变量,这会很有用。

              例如,每个都有索引。就像 item 变量在 for 循环中关闭(即,仅在其中可用)一样,index 变量在匿名范围内关闭。

              // first loop
              {
                  Integer index = -1;
                  for (Object item : things) {index += 1;
                      // ... item, index
                  }
              }
              
              // second loop
              {
                  Integer index = -1;
                  for (Object item : stuff) {index += 1;
                      // ... item, index
                  }
              }
              

              如果您没有 for 循环来提供变量范围,但您想使用通用变量名称,我有时也会使用它。

              {
                  User user = new User();
                  user.setId(0);
                  user.setName("Andy Green");
                  user.setEmail("andygreen@gmail.com");
                  users.add(user);
              }
              
              {
                  User user = new User();
                  user.setId(1);
                  user.setName("Rachel Blue");
                  user.setEmail("rachelblue@gmail.com");
                  users.add(user);
              }
              

              【讨论】:

                猜你喜欢
                • 2019-02-05
                • 2014-06-04
                • 2011-03-18
                • 1970-01-01
                • 2018-11-18
                • 1970-01-01
                • 2011-03-21
                • 1970-01-01
                相关资源
                最近更新 更多