1、jdk7之前的关闭流的操作

  1. /**
  2. * jdk7以前关闭流的方式
  3. *
  4. * @author fcant
  5. * */
  6. public class CloseResourceBeforeJava7 {
  7. private static final String FileName = "file.txt";
  8. public static void main(String[] args) throws IOException {
  9. FileInputStream inputStream = null;
  10. try {
  11. inputStream = new FileInputStream(FileName);
  12. char c1 = (char) inputStream.read();
  13. System.out.println("c1=" + c1);
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. } finally {
  17. if (inputStream != null) {
  18. inputStream.close();
  19. }
  20. }
  21. }
  22. }

2、jdk7之后try-with-resource关闭资源

实现了 **java.lang.AutoCloseable**接口(其中,它包括实现了 **java.io.Closeable** 的所有对象),可以使用作为资源。实现java.lang.AutoCloseable接口的Resource类:

  1. /**
  2. * 资源类
  3. *
  4. * @author fcant
  5. * */
  6. public class Resource implements AutoCloseable {
  7. public void sayHello() {
  8. System.out.println("hello");
  9. }
  10. @Override
  11. public void close() throws Exception {
  12. System.out.println("Resource is closed");
  13. }
  14. }
  1. /**
  2. * jdk7及以后关闭流的方式
  3. *
  4. * @author fcant
  5. * */
  6. public class CloseResourceAfterJava7 {
  7. public static void main(String[] args) {
  8. try(Resource resource = new Resource()) {
  9. resource.sayHello();
  10. } catch (Exception e) {
  11. e.printStackTrace();
  12. }
  13. }
  14. }

输出:

  1. hello
  2. Resource is closed

当存在多个打开资源的时候:

  1. /**
  2. * 资源2
  3. *
  4. * @author fcant
  5. * */
  6. public class Resource2 implements AutoCloseable {
  7. public void sayhello() {
  8. System.out.println("Resource say hello");
  9. }
  10. @Override
  11. public void close() throws Exception {
  12. System.out.println("Resource2 is closed");
  13. }
  14. }
  1. /**
  2. * jdk7及以后关闭流的方式
  3. *
  4. * @author fcant
  5. * */
  6. public class CloseResourceAfterJava7 {
  7. public static void main(String[] args) {
  8. try(Resource resource = new Resource(); Resource2 resource2 = new Resource2()) {
  9. resource.sayHello();
  10. resource2.sayhello();
  11. } catch (Exception e) {
  12. e.printStackTrace();
  13. }
  14. }
  15. }

输出:

  1. hello
  2. Resource say hello
  3. Resource2 is closed
  4. Resource is closed

3、关于异常屏蔽

A.Java7之前-不使用catch抛出异常的写法

将上面的测试类进行修改使用方法抽取异常处理不使用catch抛出异常

  1. /**
  2. * CloseResourceAfterJava7
  3. * <p>
  4. * encoding:UTF-8
  5. *
  6. * @author Fcant 下午 22:04 2020/6/26/0026
  7. */
  8. public class CloseResourceAfterJava7 {
  9. public static void main(String[] args) {
  10. try {
  11. errorTest();
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. }
  15. }
  16. private static void errorTest() throws Exception {
  17. Resource resource = null;
  18. try {
  19. resource = new Resource();
  20. resource.sayHello();
  21. }
  22. finally {
  23. if (resource != null) {
  24. resource.close();
  25. }
  26. }
  27. }
  28. }

image.png

B.Java7之前-使用catch抛出异常的写法

  1. /**
  2. * CloseResourceAfterJava7
  3. * <p>
  4. * encoding:UTF-8
  5. *
  6. * @author Fcant 下午 22:04 2020/6/26/0026
  7. */
  8. public class CloseResourceAfterJava7 {
  9. public static void main(String[] args) {
  10. try {
  11. errorTest();
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. }
  15. }
  16. private static void errorTest() throws Exception {
  17. Resource resource = null;
  18. try {
  19. resource = new Resource();
  20. resource.sayHello();
  21. } catch (Exception e) {
  22. e.printStackTrace();
  23. } finally {
  24. if (resource != null) {
  25. resource.close();
  26. }
  27. }
  28. }
  29. }

image.png

C.Java7之后-显示被Suppressed屏蔽(未使用catch抛出)[即A中的问题]的异常

①不使用catch处理异常

  1. /**
  2. * CloseResourceAfterJava7
  3. * <p>
  4. * encoding:UTF-8
  5. *
  6. * @author Fcant 下午 22:04 2020/6/26/0026
  7. */
  8. public class CloseResourceAfterJava7 {
  9. public static void main(String[] args) {
  10. try {
  11. errorTest();
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. }
  15. }
  16. private static void errorTest() throws Exception {
  17. try (Resource resource = new Resource();) {
  18. resource.sayHello();
  19. }
  20. }
  21. }

image.png

②使用catch处理异常与不使用catch一样

  1. /**
  2. * CloseResourceAfterJava7
  3. * <p>
  4. * encoding:UTF-8
  5. *
  6. * @author Fcant 下午 22:04 2020/6/26/0026
  7. */
  8. public class CloseResourceAfterJava7 {
  9. public static void main(String[] args) {
  10. try {
  11. errorTest();
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. }
  15. }
  16. private static void errorTest() throws Exception {
  17. try (Resource resource = new Resource();) {
  18. resource.sayHello();
  19. } catch (Exception e) {
  20. e.printStackTrace();
  21. }
  22. }
  23. }

image.png

D.分析编译后的class文件查看AutoCloseable怎么处理屏蔽的异常

以下是测试类编译后的class源码文件,并非研究操作的功能源码

  1. public class CloseResourceAfterJava7 {
  2. public CloseResourceAfterJava7() {
  3. }
  4. public static void main(String[] args) {
  5. try {
  6. errorTest();
  7. } catch (Exception var2) {
  8. var2.printStackTrace();
  9. }
  10. }
  11. private static void errorTest() throws Exception {
  12. Resource resource = new Resource();
  13. Throwable var1 = null;
  14. try {
  15. resource.sayHello();
  16. } catch (Throwable var10) {
  17. var1 = var10;
  18. throw var10;
  19. } finally {
  20. if (resource != null) {
  21. if (var1 != null) {
  22. try {
  23. resource.close();
  24. } catch (Throwable var9) {
  25. var1.addSuppressed(var9);
  26. }
  27. } else {
  28. resource.close();
  29. }
  30. }
  31. }
  32. }
  33. }

image.png
可以发现编译以后生成了try-catch-finally语句块 finally中的var1.addSuppressed(var9);
这里可以看到AutoCloseable底层已经转换了try catch,所以我们可以不用catch抛出异常。
另外如果我们写的不够优雅,IDEA也会提示进行转换的
image.png