I go, you should still use try-catch-finally

Brother, you thing I read before I went to switch the article also special What is so interesting, something more to say after reading ah, ah not to write another? Although the use of Java syntax is 13, older versions not very friendly. But who can guarantee that Java will not do it again a major update of it, like Java 8 as alive in the Java 6 shot dead on the beach. Java 8 is fragrant, but sooner or later want to upgrade, I quite you, brother, do not care about those dissenting voices.

This is Alice readers last week specifically to give me the information, I was really moved. Indeed, the last "I went to" read the amount of leverage, reprinted several large, including CSDN, 15000 Clause read all day. But such "I thought you have any new stunt, did not expect to use the Java 13" sounds kind of criticism are also many.

But my heart has been great. I wrote the first article from the date, the number of times the amount of hair spray like dense overhead as count them. So I decided to redouble their efforts to bring new one, "I go."

The remote review do not, because our company is also a return to work. The review of the code is still Amy's, he wrote most of the code is very beautiful, while rigorous annotation is also in place, it makes me very happy. But when I saw him useless to try-with-resources when, still can not help but curse: "! I rub, Amy, you Ah actually still use try-catch-finally"

Wang look at the code written in it.

public class Trycatchfinally {
    public static void main(String[] args) {
        BufferedReader br = null;
        try {
            br = new BufferedReader(new FileReader("/牛逼.txt"));
            String str = null;
            while ((str =br.readLine()) != null) {
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
复制代码

Hey, I feel the code is perfect ah, try-catch-finally used was quite satisfactory, especially if the file name 牛逼.txtis very bright. Do not write comments can understand this code is doing: read the contents of the file in the try block, and line by line printed to the console. If the file is not found or an error occurs IO to read and write, capture and print on the wrong stack information in the catch. Finally, close the buffered character reader BufferedReader objects in finally, the effective performance put an end to the serious consequences of the availability of resources has not been closed.

Before Java 7, try-catch-finally indeed the best way to ensure resources will be promptly closed, whether or not the program will throw an exception.

But then, the experienced reader will find two serious problems from above this code:

1) the file name "regressed .txt" includes Chinese, need to pass java.net.URLDecoderclass decode()method of their escape, otherwise this code at run time would definitely want to throw a file not found exception.

2) If you directly through new FileReader("牛逼.txt")to create a FileReader object "regressed .txt" src needs and projects at the same level directory, or file can not be found will also throw exceptions. But in most cases, (configuration) files will be placed under the resources directory, easy to compile the file appears in the classes directory, see below.

In order to solve these two problems, we need to optimize the code:

public class TrycatchfinallyDecoder {
    public static void main(String[] args) {
        BufferedReader br = null;
        try {
            String path = TrycatchfinallyDecoder.class.getResource("/牛逼.txt").getFile();
            String decodePath = URLDecoder.decode(path,"utf-8");
            br = new BufferedReader(new FileReader(decodePath));

            String str = null;
            while ((str =br.readLine()) != null) {
                System.out.println(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
复制代码

Run this code, you can program the contents of the file are correct output to the console. But if you are on the "clean" the word of longing, then this code will feel very bloated, especially finally the code, like a snowflake filling 12 bottles of beer bellies.

Online see a God figure of ridicule Python programmers Java programmers, direct copy over (invasion deleted), to make you a happy:

Moreover, try-catch-finally start to finish there is a serious risk: try the br.readLine()possible throws IOException, finally it is br.close()also likely to be thrown IOException. If the two are unfortunately throws IOException, debugging tasks that the program becomes complicated again, in the end at which a mistake, you need to spend a lot of effort, this is the result we want to see.

In order to simulate the above, we define a class from MyfinallyReadLineThrow, which has two methods, respectively, readLine()and close(), are active thrown method body.

class MyfinallyReadLineThrow {
    public void close() throws Exception {
        throw new Exception("close");
    }

    public void readLine() throws Exception {
        throw new Exception("readLine");
    }
}
复制代码

We then main()use try-finally a way to call MyfinallyReadLineThrow methods readLine()and close()methods:

public class TryfinallyCustomReadLineThrow {
    public static void main(String[] args) throws Exception {
        MyfinallyReadLineThrow myThrow = null;
        try {
            myThrow = new MyfinallyReadLineThrow();
            myThrow.readLine();
        } finally {
            myThrow.close();
        }
    }
}
复制代码

After running the above code, the error stack as follows:

Exception in thread "main" java.lang.Exception: close
	at com.cmower.dzone.trycatchfinally.MyfinallyOutThrow.close(TryfinallyCustomOutThrow.java:17)
	at com.cmower.dzone.trycatchfinally.TryfinallyCustomOutThrow.main(TryfinallyCustomOutThrow.java:10)
复制代码

readLine()Exception information method is now being close()eaten stack information method, which is bound to make us mistakenly think the goal is to investigate close()methods instead readLine()- although it is also the object should be skeptical.

But with the introduction of try-with-resources, these problems would be solved, as long as the need to release resources (such as BufferedReader) implements AutoCloseable interface. With the following solutions, we come to the right before finally code block thin.

try (BufferedReader br = new BufferedReader(new FileReader(decodePath));) {
    String str = null;
    while ((str =br.readLine()) != null) {
        System.out.println(str);
    }
} catch (IOException e) {
    e.printStackTrace();
}
复制代码

You see, finally block is gone, replaced by the resource to be released after the try to write ()in. If there are multiple resources (BufferedReader and PrintWriter) to be released, you can directly ()add in.

try (BufferedReader br = new BufferedReader(new FileReader(decodePath));
     PrintWriter writer = new PrintWriter(new File(writePath))) {
    String str = null;
    while ((str =br.readLine()) != null) {
        writer.print(str);
    }
} catch (IOException e) {
    e.printStackTrace();
}
复制代码

If you want to release the custom resource, so long as it realized AutoCloseable interface and provides close()methods you can.

public class TrywithresourcesCustom {
    public static void main(String[] args) {
        try (MyResource resource = new MyResource();) {
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

class MyResource implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("关闭自定义资源");
    }
}
复制代码

After executing the code outputs the result as follows:

关闭自定义资源
复制代码

Is not it amazing? We try ()are just a new MyResource object, other did nothing, yet close()output statement method is performed. Want to know why? Take a look at the bytecode decompiling it.

class MyResource implements AutoCloseable {
    MyResource() {
    }

    public void close() throws Exception {
        System.out.println("关闭自定义资源");
    }
}

public class TrywithresourcesCustom {
    public TrywithresourcesCustom() {
    }

    public static void main(String[] args) {
        try {
            MyResource resource = new MyResource();
            resource.close();
        } catch (Exception var2) {
            var2.printStackTrace();
        }

    }
}
复制代码

Hey, compiler, took were transformed into a try-with-resources, try calling in the close()method.

Next, we add in a custom class out()method,

class MyResourceOut implements AutoCloseable {
    @Override
    public void close() throws Exception {
        System.out.println("关闭自定义资源");
    }

    public void out() throws Exception{
        System.out.println("沉默王二,一枚有趣的程序员");
    }
}
复制代码

This time, in what we call in the try out()method:

public class TrywithresourcesCustomOut {
    public static void main(String[] args) {
        try (MyResourceOut resource = new MyResourceOut();) {
            resource.out();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
复制代码

Then look at the decompiled bytecode:

public class TrywithresourcesCustomOut {
    public TrywithresourcesCustomOut() {
    }

    public static void main(String[] args) {
        try {
            MyResourceOut resource = new MyResourceOut();

            try {
                resource.out();
            } catch (Throwable var5) {
                try {
                    resource.close();
                } catch (Throwable var4) {
                    var5.addSuppressed(var4);
                }

                throw var5;
            }

            resource.close();
        } catch (Exception var6) {
            var6.printStackTrace();
        }

    }
}
复制代码

This time, catchblock the initiative to call resource.close(), and there is a very critical code var5.addSuppressed(var4). What use is it? When an exception is thrown, there may be other unusual because the exception is suppressed, and thus can not throw properly. In this case by addSuppressed()a method of suppressing these methods are recorded. Suppressed exception occurs in abnormal stack information thrown in, you can also getSuppressed()acquire these anomalies methods. The benefit of this is not lost any exception, to facilitate our developers to debug.

Wow, have not thought that our previous example - in a try-finally, the readLine()exception information method is now being close()stack information method of eating. Now, with try-with-resources, look at the role and readLine()consistent approach out()method will not be close()eaten.

In close()and out()methods direct throw an exception:

class MyResourceOutThrow implements AutoCloseable {
    @Override
    public void close() throws Exception {
        throw  new Exception("close()");
    }

    public void out() throws Exception{
        throw new Exception("out()");
    }
}
复制代码

Call these two methods:

public class TrywithresourcesCustomOutThrow {
    public static void main(String[] args) {
        try (MyResourceOutThrow resource = new MyResourceOutThrow();) {
            resource.out();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
复制代码

The output results of the program are as follows:

java.lang.Exception: out()
	at com.cmower.dzone.trycatchfinally.MyResourceOutThrow.out(TrywithresourcesCustomOutThrow.java:20)
	at com.cmower.dzone.trycatchfinally.TrywithresourcesCustomOutThrow.main(TrywithresourcesCustomOutThrow.java:6)
	Suppressed: java.lang.Exception: close()
		at com.cmower.dzone.trycatchfinally.MyResourceOutThrow.close(TrywithresourcesCustomOutThrow.java:16)
		at com.cmower.dzone.trycatchfinally.TrywithresourcesCustomOutThrow.main(TrywithresourcesCustomOutThrow.java:5)
复制代码

Well, not this time around, out()the exception stack information printed out, and close()stack information method of adding a keyword on Suppressed. Glance, good good, I like it.

To summarize, when dealing with the resources that must be closed, always consider the limited use try-with-resources, rather than try-catch-finally. The former generates the code more concise, clear and exception information generated more tricky. Promise me, OK? Do not use the try-catch-finally.

Acknowledgments

Well, my dear readers, that's the entire contents of this article, I am not feeling and learn new knowledge? I was silent king, one interesting programmer. The original is not easy, they must not white vote, you praise a point of it for this article , it will be my writing more quality articles strongest power.

If you think your article a little help, micro-channel search "  silence the king,  " the first time to read, respond to [ 666 ] more 500G HD instructional videos I carefully prepared for you (already categorized). This article  GitHub  already included, there is a complete interview giant test center, welcomed the Star.

Guess you like

Origin juejin.im/post/5e87cb9be51d4546cf777342