在这里,我们将给大家分享关于使用try-catch-finally等效于Java7try-with-resources字节码是什么?的知识,让您更了解javatrycatchfinally作用的本质,
在这里,我们将给大家分享关于使用try-catch-finally等效于Java 7 try-with-resources字节码是什么?的知识,让您更了解java try catch finally作用的本质,同时也会涉及到如何更有效地Effective Java 第三版读书笔记——条款9:使用 try-with-resources 语句替代 try-finally 语句、Java 9中的try-with-resources中的有效final变量?、Java – Try with Resources、java – try-with-resources中的死代码警告,但不是在翻译的try-catch-finally中的内容。
本文目录一览:- 使用try-catch-finally等效于Java 7 try-with-resources字节码是什么?(java try catch finally作用)
- Effective Java 第三版读书笔记——条款9:使用 try-with-resources 语句替代 try-finally 语句
- Java 9中的try-with-resources中的有效final变量?
- Java – Try with Resources
- java – try-with-resources中的死代码警告,但不是在翻译的try-catch-finally中
使用try-catch-finally等效于Java 7 try-with-resources字节码是什么?(java try catch finally作用)
我试图通过使用常规try-catch-finally语句重新创建新的try-with-
resources语句来了解其工作方式。给定以下使用Java
7 try-with-resources的测试类:
import java.io.IOException;import java.util.zip.GZIPOutputStream;public class TryWithResources { public static void main(String[] args) { try (GZIPOutputStream gzip = new GZIPOutputStream(System.out)) { gzip.write("TEST".getBytes("UTF-8")); } catch (IOException ioe) { ioe.printStackTrace(); } }}
您将如何重写此类以使用try-catch-finally语句,该语句所产生的字节码与try-with-
resources语句所产生的字节码完全相同?同样,当使用两个资源时,同样的问题,如以下示例所示:
import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.zip.GZIPOutputStream;public class TryWithResources2 { public static void main(String[] args) { try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); GZIPOutputStream gzip = new GZIPOutputStream(baos)) { gzip.write("TEST".getBytes("UTF-8")); } catch (IOException ioe) { ioe.printStackTrace(); } }}
答案1
小编典典对于TryWithResources
该类,以下类产生与try-with-resources等效的字节码:
import java.io.IOException;import java.util.zip.GZIPOutputStream;public class TryCatchFinally { public static void main(String[] args) { try { final GZIPOutputStream gzip = new GZIPOutputStream(System.out); Throwable gzipEx = null; try { gzip.write("TEST".getBytes("UTF-8")); } catch (Throwable t) { gzipEx = t; throw t; } finally { if (gzip != null) { if (gzipEx != null) { try { gzip.close(); } catch (Throwable t) { gzipEx.addSuppressed(t); } } else { gzip.close(); } } } } catch (IOException ioe) { ioe.printStackTrace(); } }}
使用Sun JDK 1.7.0,在这两个主要的方法字节码和异常表TryWithResources
和TryCatchFinally
类是:
stack=3, locals=6, args_size=1 0: new #2 // class java/util/zip/GZIPOutputStream 3: dup 4: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream; 7: invokespecial #4 // Method java/util/zip/GZIPOutputStream."<init>":(Ljava/io/OutputStream;)V 10: astore_1 11: aconst_null 12: astore_2 13: aload_1 14: ldc #5 // String TEST 16: ldc #6 // String UTF-8 18: invokevirtual #7 // Method java/lang/String.getBytes:(Ljava/lang/String;)[B 21: invokevirtual #8 // Method java/util/zip/GZIPOutputStream.write:([B)V 24: aload_1 25: ifnull 95 28: aload_2 29: ifnull 48 32: aload_1 33: invokevirtual #9 // Method java/util/zip/GZIPOutputStream.close:()V 36: goto 95 39: astore_3 40: aload_2 41: aload_3 42: invokevirtual #11 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V 45: goto 95 48: aload_1 49: invokevirtual #9 // Method java/util/zip/GZIPOutputStream.close:()V 52: goto 95 55: astore_3 56: aload_3 57: astore_2 58: aload_3 59: athrow 60: astore 4 62: aload_1 63: ifnull 92 66: aload_2 67: ifnull 88 70: aload_1 71: invokevirtual #9 // Method java/util/zip/GZIPOutputStream.close:()V 74: goto 92 77: astore 5 79: aload_2 80: aload 5 82: invokevirtual #11 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V 85: goto 92 88: aload_1 89: invokevirtual #9 // Method java/util/zip/GZIPOutputStream.close:()V 92: aload 4 94: athrow 95: goto 103 98: astore_1 99: aload_1 100: invokevirtual #13 // Method java/io/IOException.printStackTrace:()V 103: return Exception table: from to target type 32 36 39 Class java/lang/Throwable 13 24 55 Class java/lang/Throwable 13 24 60 any 70 74 77 Class java/lang/Throwable 55 62 60 any 0 95 98 Class java/io/IOException
对于TryWithResources2
该类,以下类产生与try-with-resources等效的字节码:
import java.io.ByteArrayOutputStream;import java.io.IOException;import java.util.zip.GZIPOutputStream;public class TryCatchFinally2 { public static void main(String[] args) { try { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); Throwable baosEx = null; try { final GZIPOutputStream gzip = new GZIPOutputStream(baos); Throwable gzipEx = null; try { gzip.write("TEST".getBytes("UTF-8")); } catch (Throwable t) { gzipEx = t; throw t; } finally { if (gzip != null) { if (gzipEx != null) { try { gzip.close(); } catch (Throwable t) { gzipEx.addSuppressed(t); } } else { gzip.close(); } } } } catch (Throwable t) { baosEx = t; throw t; } finally { if (baos != null) { if (baosEx != null) { try { baos.close(); } catch (Throwable t) { baosEx.addSuppressed(t); } } else { baos.close(); } } } } catch (IOException ioe) { ioe.printStackTrace(); } }}
TryWithResources2
和TryCatchFinally2
类中主要方法的字节码和异常表是:
stack=3, locals=10, args_size=1 0: new #2 // class java/io/ByteArrayOutputStream 3: dup 4: invokespecial #3 // Method java/io/ByteArrayOutputStream."<init>":()V 7: astore_1 8: aconst_null 9: astore_2 10: new #4 // class java/util/zip/GZIPOutputStream 13: dup 14: aload_1 15: invokespecial #5 // Method java/util/zip/GZIPOutputStream."<init>":(Ljava/io/OutputStream;)V 18: astore_3 19: aconst_null 20: astore 4 22: aload_3 23: ldc #6 // String TEST 25: ldc #7 // String UTF-8 27: invokevirtual #8 // Method java/lang/String.getBytes:(Ljava/lang/String;)[B 30: invokevirtual #9 // Method java/util/zip/GZIPOutputStream.write:([B)V 33: aload_3 34: ifnull 114 37: aload 4 39: ifnull 61 42: aload_3 43: invokevirtual #10 // Method java/util/zip/GZIPOutputStream.close:()V 46: goto 114 49: astore 5 51: aload 4 53: aload 5 55: invokevirtual #12 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V 58: goto 114 61: aload_3 62: invokevirtual #10 // Method java/util/zip/GZIPOutputStream.close:()V 65: goto 114 68: astore 5 70: aload 5 72: astore 4 74: aload 5 76: athrow 77: astore 6 79: aload_3 80: ifnull 111 83: aload 4 85: ifnull 107 88: aload_3 89: invokevirtual #10 // Method java/util/zip/GZIPOutputStream.close:()V 92: goto 111 95: astore 7 97: aload 4 99: aload 7 101: invokevirtual #12 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V 104: goto 111 107: aload_3 108: invokevirtual #10 // Method java/util/zip/GZIPOutputStream.close:()V 111: aload 6 113: athrow 114: aload_1 115: ifnull 185 118: aload_2 119: ifnull 138 122: aload_1 123: invokevirtual #13 // Method java/io/ByteArrayOutputStream.close:()V 126: goto 185 129: astore_3 130: aload_2 131: aload_3 132: invokevirtual #12 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V 135: goto 185 138: aload_1 139: invokevirtual #13 // Method java/io/ByteArrayOutputStream.close:()V 142: goto 185 145: astore_3 146: aload_3 147: astore_2 148: aload_3 149: athrow 150: astore 8 152: aload_1 153: ifnull 182 156: aload_2 157: ifnull 178 160: aload_1 161: invokevirtual #13 // Method java/io/ByteArrayOutputStream.close:()V 164: goto 182 167: astore 9 169: aload_2 170: aload 9 172: invokevirtual #12 // Method java/lang/Throwable.addSuppressed:(Ljava/lang/Throwable;)V 175: goto 182 178: aload_1 179: invokevirtual #13 // Method java/io/ByteArrayOutputStream.close:()V 182: aload 8 184: athrow 185: goto 193 188: astore_1 189: aload_1 190: invokevirtual #15 // Method java/io/IOException.printStackTrace:()V 193: return Exception table: from to target type 42 46 49 Class java/lang/Throwable 22 33 68 Class java/lang/Throwable 22 33 77 any 88 92 95 Class java/lang/Throwable 68 79 77 any 122 126 129 Class java/lang/Throwable 10 114 145 Class java/lang/Throwable 10 114 150 any 160 164 167 Class java/lang/Throwable 145 152 150 any 0 185 188 Class java/io/IOException
Effective Java 第三版读书笔记——条款9:使用 try-with-resources 语句替代 try-finally 语句
Java 类库中包含许多必须手动调用 close
方法来关闭的资源, 比如InputStream
、OutputStream
和 java.sql.Connection
。
从以往来看,try-finally 语句是保证资源正确关闭的最佳方式,即使是在程序抛出异常或返回的情况下:
// try-finally - No longer the best way to close resources!
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
br.close();
}
}
这看起来并不差,但是当添加第二个资源时,情况会变得很糟:
// try-finally is ugly when used with more than one resource!
static void copy(String src, String dst) throws IOException {
InputStream in = new FileInputStream(src);
try {
OutputStream out = new FileOutputStream(dst);
try {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
} finally {
out.close();
}
} finally {
in.close();
}
}
即使是用 try-finally 语句关闭资源的正确代码(如前面两个代码示例所示)也有一个微妙的缺陷。 try 块和 finally 块中的代码都可以抛出异常。 例如,在 firstLineOfFile
方法中,由于底层物理设备发生故障,对 readLine
方法的调用可能会引发异常,并且由于相同的原因,调用 close
方法可能也会失败。 在这种情况下,第二个异常完全冲掉了第一个异常。 在异常堆栈跟踪中没有第一个异常的记录,这可能使实际系统中的调试变得非常复杂——通常你想要看到第一个异常来诊断问题。 虽然可以编写代码来抑制第二个异常,但是实际上没有人这样做,因为它太冗长了。
当 Java 7 引入了 try-with-resources 语句时,所有这些问题都得到了解决。要使用这个构造,资源必须实现 AutoCloseable
接口,该接口由一个返回类型为 void
的 close
方法组成。Java 类库和第三方类库中的许多类和接口现在都实现或继承了 AutoCloseable
接口。如果你编写的类表示必须关闭的资源,那么这个类也应该实现 AutoCloseable
接口。
下面是第一个使用 try-with-resources 语句的示例:
// try-with-resources - the the best way to close resources!
static String firstLineOfFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(
new FileReader(path))) {
return br.readLine();
}
}
下面是第二个使用 try-with-resources 语句的示例:
// try-with-resources on multiple resources - short and sweet
static void copy(String src, String dst) throws IOException {
try (InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst)) {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
}
}
try-with-resources 版本比原始版本更精简,具有更好的可读性,而且提供了更好的可诊断性。 考虑 firstLineOfFile
方法。 如果调用 readLine
方法和(不可见的)close
方法都抛出异常,则后一个异常将被抑制(suppressed),而不是前者。 事实上,为了保留你真正想看到的异常,可能会有多个异常被抑制。 这些被抑制的异常没有被抛弃,而是打印在堆栈跟踪中,并标注为被抑制了。你也可以使用 getSuppressed
方法在程序中访问它们,该方法在 Java 7 被添加到 Throwable
中。
还可以在 try-with-resources 语句中添加 catch 子句,就像在常规的 try-finally 语句中一样。这允许你处理异常,而不会用另一层嵌套污染代码。下面是一个稍微有些不自然的例子,它不会抛出异常,但是如果它不能打开或读取文件,则返回默认值:
// try-with-resources with a catch clause
static String firstLineOfFile(String path, String defaultVal) {
try (BufferedReader br = new BufferedReader(
new FileReader(path))) {
return br.readLine();
} catch (IOException e) {
return defaultVal;
}
}
结论明确:在处理必须关闭的资源时,使用 try-with-resources 语句替代 try-finally 语句。 这会使生成的代码更简洁、更清晰,并且抛出的异常在调试时更有用。
Java 9中的try-with-resources中的有效final变量?
在 Try with Resource 语句中使用的任何变量都需要在 Try 语句中声明,直至 Java 8 版本。从Java 9开始,此限制已被删除,并且任何final 或有效final变量已在尝试阻止。 Effectively Final 表示变量一旦初始化就无法更改。
示例
import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; public class EffectivelyFinalTest { private static File file = new File("try_resources.txt"); public static void main(String args[]) throws IOException { file.createNewFile(); BufferedReader bufferedReader = new BufferedReader(new FileReader(file)); <strong>try</strong>(<strong>bufferedReader</strong>) { System.out.println("Can Use Final or Effectively Final in Try with Resources!"); } finally { System.out.println("In finally block"); } } }
输出
<strong>Can Use Final or Effectively Final in Try with Resources! In finally block</strong>
以上就是Java 9中的try-with-resources中的有效final变量?的详细内容,更多请关注php中文网其它相关文章!
Java – Try with Resources
1. Overview
Support for try-with-resources – introduced in Java 7 – allows us to declare resources to be used in a try block with the assurance that the resources will be closed when after the execution of that block.
The resources declared must implement the AutoCloseable interface.
2. Using try-with-resources
Simply put, to be auto-closed, a resource must be both declared and initialized inside the try, as shown below:
1
2
3
|
try
(PrintWriter writer =
new
PrintWriter(
new
File(
"test.txt"
))) {
writer.println(
"Hello World"
);
}
|
3. Replacing try–catch-finally With try-with-resources
The simple and obvious way to use the new try-with-resources functionality is to replace the traditional and verbose try-catch-finally block.
Let''s compare the following code samples – first is a typical try-catch-finally block, then the new approach, using an equivalent try-with-resources block:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
Scanner scanner =
null
;
try
{
scanner =
new
Scanner(
new
File(
"test.txt"
));
while
(scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
}
catch
(FileNotFoundException e) {
e.printStackTrace();
}
finally
{
if
(scanner !=
null
) {
scanner.close();
}
}
|
And here''s the super succinct solution using try-with-resources:
1
2
3
4
5
6
7
|
try
(Scanner scanner =
new
Scanner(
new
File(
"test.txt"
))) {
while
(scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
}
catch
(FileNotFoundException fnfe) {
fnfe.printStackTrace();
}
|
Here''s where you can further explore the Scanner class.
4. try-with-resources with Multiple Resources
Multiple resources can be declared just fine in a try-with-resources block by separating them with a semicolon:
1
2
3
4
5
6
|
try
(Scanner scanner =
new
Scanner(
new
File(
"testRead.txt"
));
PrintWriter writer =
new
PrintWriter(
new
File(
"testWrite.txt"
))) {
while
(scanner.hasNext()) {
writer.print(scanner.nextLine());
}
}
|
5. A Custom Resource with AutoCloseable
To construct a custom resource that will be correctly handled by a try-with-resources block, the class should implement the Closeable or AutoCloseable interfaces, and override the close method:
1
2
3
4
5
6
|
public
class
MyResource
implements
AutoCloseable {
@Override
public
void
close()
throws
Exception {
System.out.println(
"Closed MyResource"
);
}
}
|
6. Resource Closing Order
Resources that were defined/acquired first will be closed last; let''s look at an example of this behavior:
Resource 1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public
class
AutoCloseableResourcesFirst
implements
AutoCloseable {
public
AutoCloseableResourcesFirst() {
System.out.println(
"Constructor -> AutoCloseableResources_First"
);
}
public
void
doSomething() {
System.out.println(
"Something -> AutoCloseableResources_First"
);
}
@Override
public
void
close()
throws
Exception {
System.out.println(
"Closed AutoCloseableResources_First"
);
}
}
|
Resource 2:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
public
class
AutoCloseableResourcesSecond
implements
AutoCloseable {
public
AutoCloseableResourcesSecond() {
System.out.println(
"Constructor -> AutoCloseableResources_Second"
);
}
public
void
doSomething() {
System.out.println(
"Something -> AutoCloseableResources_Second"
);
}
@Override
public
void
close()
throws
Exception {
System.out.println(
"Closed AutoCloseableResources_Second"
);
}
}
|
Code:
1
2
3
4
5
6
7
8
|
private
void
orderOfClosingResources()
throws
Exception {
try
(AutoCloseableResourcesFirst af =
new
AutoCloseableResourcesFirst();
AutoCloseableResourcesSecond as =
new
AutoCloseableResourcesSecond()) {
af.doSomething();
as.doSomething();
}
}
|
Output:
Constructor -> AutoCloseableResources_First
Constructor -> AutoCloseableResources_Second
Something -> AutoCloseableResources_First
Something -> AutoCloseableResources_Second
Closed AutoCloseableResources_Second
Closed AutoCloseableResources_First
7. catch & finally
A try-with-resources block can still have the catch and finally blocks – which will work in the same way as with a traditional try block.
8. Conclusion
In this article, we have discussed how to use try-with-resources, how to replace try, catch and finally with try-with-resources, building custom resources with AutoCloseable and order in which resources are closed.
The complete source code for the example is available in this GitHub project.
java – try-with-resources中的死代码警告,但不是在翻译的try-catch-finally中
try
-with-resources结构.偶然的Throw()方法被声明为抛出OccasionalException,Resource的close()方法抛出一个CloseException. Eclipse(版本:Neon Release(4.6.0),Build id:20160613-1800)在标有//死代码的行上添加一个警告,表示该分支是死代码.隐含地,Eclipse确认标有//活动代码的行不是死代码.
Object tryWithResources() throws OccasionalException { Object value = null; try (Resource resource = new Resource()) { occasionallyThrow(); value = new Object(); } catch (CloseException e) { if (value == null) { // alive code } else { // dead code } } return value; }
我很困惑.如果偶然的Throw()抛出其OccasionalException,那么try-with-resources应该将其作为主要异常捕获,然后尝试关闭资源.如果关闭资源会抛出一个CloseException,那么它将在OccasionalException下被抑制,因此不会捕获CloseException.因此,唯一需要捕获的CloseException是在try中的块成功完成时,这意味着该值为非null.所以看起来“死代码”实际上是活着的,而“活着代码”实际上已经死了.我不确定编译器实际上应该在这里识别出什么,但至少,这里的“死代码”似乎不应该被称为死.
更复杂的是,不使用try-with-resources表单的翻译表单根本没有标记任何死代码警告. (我非常有信心,基于14.20.3.2. Extended try-with-resources,我的翻译是正确的,但如果这里有错误,我不会感到惊讶……)
Object expandedTry() throws OccasionalException { Object value = null; try { Resource resource = new Resource(); Throwable $primary = null; try { occasionallyThrow(); value = new Object(); } catch (Throwable t) { $primary = t; throw t; } finally { if (resource != null) { if ($primary != null) { try { resource.close(); } catch (Throwable $suppressed) { $primary.addSuppressed($suppressed); } } else { resource.close(); } } } } catch (CloseException e) { if (value == null) { // alive (not dead!) } else { // alive } } return value; }
我是否遗漏了一些东西会使if-else中的任何一个分支死于其中一个,而不是另一个?
完整代码
这是包含辅助异常类型,Resource类和顶级类定义的完整代码.
public class TestTryWithResources { /** Exception thrown by Resource's close() method */ @SuppressWarnings("serial") static class CloseException extends Exception {} /** AutoCloseable declared to throw a CloseException */ static class Resource implements AutoCloseable { @Override public void close() throws CloseException {} } /** An occasionally thrown exception */ @SuppressWarnings("serial") static class OccasionalException extends Exception {} /** Method declared to throw an occasional exception */ void occasionallyThrow() throws OccasionalException {} /* * Method using try-with-resources. Eclipse warns that the * portion marked with "// dead code" is Dead code. */ Object tryWithResources() throws OccasionalException { Object value = null; try (Resource resource = new Resource()) { occasionallyThrow(); value = new Object(); } catch (CloseException e) { if (value == null) { // alive code } else { // dead code } } return value; } /* * Method not using try-with-resources. This is the translation * of the try-with-resources in tryWithResources,according to * [14.20.3 try-with-resources][1]. Eclipse does not warn about * any of the code being Dead code. * * [1]: https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.20.3 */ Object expandedTry() throws OccasionalException { Object value = null; try { Resource resource = new Resource(); Throwable $primary = null; try { occasionallyThrow(); value = new Object(); } catch (Throwable t) { $primary = t; throw t; } finally { if (resource != null) { if ($primary != null) { try { resource.close(); } catch (Throwable $suppressed) { $primary.addSuppressed($suppressed); } } else { resource.close(); } } } } catch (CloseException e) { if (value == null) { // alive } else { // alive } } return value; } }
回应评论
Amin J’s answer建议在设置值之后使用资源来改变Eclipse的代码分析.但这不起作用.在使用资源之后,例如通过打印它,Luna和Neon中仍然存在死码警告:
解决方法
try-with-resources语句确保在语句结束时关闭每个资源.
因此,例如,如果您更改代码以在值为(下面的代码)后使用资源,则它不会警告您死代码(但在Eclipse Luna上测试).
Object tryWithResources() throws OccasionalException { Object value = null; try (Resource resource = new Resource()) { occasionallyThrow(); value = new Object(); resource.someMethod(); // using the resource,so eclipse thinks it's not closed yet (correctly) } catch (CloseException e) { if (value == null) { // alive code } else { // dead code } } return value; }
UPDATE
这是我在设置值后使用资源(在本例中为reader)测试的实际代码.
Object val = null; try (BufferedReader reader = new BufferedReader(new FileReader("C:\\file.txt"))) { val = new Object(); System.out.println("got here"); reader.readLine(); } catch(IOException e){ System.out.println("io ex"); if ( val == null){ } else{ } }
我们今天的关于使用try-catch-finally等效于Java 7 try-with-resources字节码是什么?和java try catch finally作用的分享已经告一段落,感谢您的关注,如果您想了解更多关于Effective Java 第三版读书笔记——条款9:使用 try-with-resources 语句替代 try-finally 语句、Java 9中的try-with-resources中的有效final变量?、Java – Try with Resources、java – try-with-resources中的死代码警告,但不是在翻译的try-catch-finally中的相关信息,请在本站查询。
本文标签: