Dùng try-with-resource để tránh duplicate code

try-with-resource được giới thiệu trong java 7, đảm bảo các tài nguyên được sử dụng bởi các instance class khai báo trong khối try sẽ được giải phóng khi khối try block hoàn tất hoặc có exception được ném ra. Lưu ý rằng các tài nguyên này phải implement AutoCloseable interface

Cách sử dụng try-with-resource 

Để các tài nguyên tự động đóng kết nối sau khi hoàn tất hoặc nếu có exception xảy ra, các tài nguyên này phải được khai báo bên trong từ khoá try.

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;

class TryWithResource {
    public static void main(String args[]) {
        try (PrintWriter writer = new PrintWriter(new File("test.txt"))) { 
            writer.println("Hello World");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}

Instance PrintWriter writer đang sử dụng file test.txt để thao tác, writer được khai báo bên trong khối try, vì vậy sau khi khối lệnh try thực thi xong, nó được tự động ngắt kết nối với file test.txt (writer.close())

Thay thế try-catch-finally bằng try-with-resource

Chúng ta thường sử dụng try-catch-finally để đảm bảo rằng các tài nguyên được đóng khi khối lệnh trong try thực hiện xong, hoặc có exception ném ra. Việc này thường lặp đi lặp lại khiến cho code bị trùng lặp khá nhiều. Hãy xem ví dụ bên dưới.

import java.io.FileInputStream;
import java.io.IOException;
 
class ReadFile {
    public static void main(String args[]) {
        FileInputStream fin = null;
        try {
            fin = new FileInputStream("/Users/nguyenthanhhai/Desktop/test.txt");
            System.out.println("FileContents :");
            //read characters from FileInputStream and write them
            int ch;
            while ((ch = fin.read()) != -1)
                System.out.print((char) ch);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fin != null)
                    fin.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Đây là một hàm đọc file thông thường sử dụng FileInputStream. Trong quá khứ chúng ta phải lặp lại đoạn code trong khối finally rất nhiều chỉ nhầm mục đích đảm bảo đóng kết nối của FileInputStream.

Đoạn code trên sẽ tương ứng khi sử dụng try-with-resource sau

import java.io.FileInputStream;
import java.io.IOException;

class ReadFile {
    public static void main(String args[]) {
        try (FileInputStream fin = new FileInputStream("/Users/nguyenthanhhai/Desktop/test.txt")) {
            System.out.println("FileContents :");
            //read characters from FileInputStream and write them
            int ch;
            while ((ch = fin.read()) != -1)
                System.out.print((char) ch);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Như vậy đoạn code trên của chúng ta chỉ cần quan tâm đến logic của method để lại việc đóng kết nối cho try-with-resource lo =). Hãy tưởng tượng rất nhiều nơi đọc file sử dụng các tài nguyên khác nhau như FileInputStream. FileReader, BufferedReader etc. thì code sẽ giảm trùng lặp đáng kể đấy.

try-with-resource với nhiều tài nguyên 

Sẽ có những lúc chúng ta sử dụng nhiều tài nguyên như Scanner, PrintWriter etc với nhau chứ không nhất thiết chỉ được một tài nguyên thì làm sao để đóng kết nối tất cả chúng đây

Đơn giản, chúng ta chỉ cần khai báo tất cả chúng bên trong try được ngăn cách nhau bởi dấu “;”. 

try (Scanner scanner = new Scanner(new File("testRead.txt"));
    PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
    while (scanner.hasNext()) {
    writer.print(scanner.nextLine());
    }
}

Tạo một class tự động đóng kết nối với AutoCloseable

Để tạo một class tự động đóng kết nối sử dụng với try-with-resource chúng ta chỉ cần implement AutoCloseable interface và override close() method.

import java.io.IOException;

class MyClass implements AutoCloseable {
    @Override
    public void close() {
        System.out.println("Closed MyResource");
    }
}

class Example {
    public static void main(String args[]) {
        try (MyClass myClass = new MyClass()) {
            throw new IOException("demo");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Output:

Closed MyResource
java.io.IOException: demo
at ReadFile.main(Main.java:13)

finally với try-with-resource

Khối lệnh try-with-resource sẽ vẫn hoạt động với finally. Việc sử dụng try-with-resource với mục tiêu tránh trùng lặp bằng việc tự động đóng kết nối các tài nguyên.

import java.io.IOException;

class MyClass implements AutoCloseable {
    @Override
    public void close() {
        System.out.println("Closed MyResource");
    }
}

class Example {
    public static void main(String args[]) {
        try (MyClass myClass = new MyClass()) {
            throw new IOException("demo");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            System.out.println("finally");
        }
    }
}

Output:

java.io.IOException: demo
Closed MyResource
at Example.main(Main.java:13)
finally

Lời kết

Qua bài viết này hy vọng sẽ phần nào giúp các bạn tối giản code hơn trong xử lý exception. Các bạn hoàn toàn có thể sử dụng try-catch-finally truyền thống, thế nhưng hãy cân nhắc sử dụng công nghệ mới nhé.

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x