วิธีใช้ Try With Resource ใน Java
วิธีจัดการข้อยกเว้นโดยใช้คำสั่ง try-with-resource
โครงสร้าง Java try with resourceหรือที่เรียกว่าJava try-with-resourcesเป็นกลไกจัดการข้อยกเว้นที่สามารถปิดรีซอร์สโดยอัตโนมัติ เช่น Java InputStream หรือ JDBC Connection เมื่อคุณดำเนินการเสร็จสิ้น
Oracle ได้เพิ่มการลองใช้ด้วยการสร้างทรัพยากรให้กับภาษา Java ในปี 2554 เพื่อช่วยรับประกันว่าออบเจกต์ต่างๆ เช่น ซ็อกเก็ตเครือข่าย การเชื่อมต่อฐานข้อมูล และการอ้างอิงไปยังไฟล์และโฟลเดอร์จะถูกยกเลิกอย่างสมบูรณ์หลังการใช้งาน การไม่สามารถปิดทรัพยากรเหล่านี้หลังจากที่นักพัฒนาเปิดที่จับอาจทำให้หน่วยความจำรั่ว ทริก เกอร์รูทีนการรวบรวมขยะที่หลีกเลี่ยงได้และทำให้ CPU ของเซิร์ฟเวอร์เครียด
· ก่อน Java 7
· จะใช้คำสั่ง try-with-resource ได้อย่างไร?
· เหตุใดฉันจึงต้องใช้คำสั่ง try-with-resource?
· ตัวอย่าง
· ข้อยกเว้นที่ถูกระงับ
· ข้อดีของการใช้ try-with-resources
· try-with-resources ด้วยหลาย Resources
· Java 9 — ตัวแปรสุดท้ายที่มีประสิทธิภาพ
ก่อน Java 7
ใน Java หากคุณใช้รีซอร์ส เช่น สตรีมอินพุตหรือเอาท์พุต คุณต้องปิดรีซอร์สทุกครั้งหลังใช้งาน นอกจากนี้ยังสามารถส่งข้อยกเว้นดังนั้นจึงต้องอยู่ในบล็อกtry-catch การปิดจะต้องอยู่ในบล็อกสุดท้าย นี่เป็นวิธีที่น้อยที่สุดจนถึง Java 7 สิ่งนี้มีข้อเสียหลายประการ:
- คุณต้องตรวจสอบว่าทรัพยากรของคุณเป็นโมฆะหรือไม่ก่อนที่จะปิด
- การปิดตัวเองอาจทำให้เกิดข้อยกเว้น ดังนั้นในที่สุด คุณ จึงต้องมีtry-catch อีกครั้ง
- โปรแกรมเมอร์มักจะลืมปิดทรัพยากรของตน
จะใช้คำสั่ง try-with-resource ได้อย่างไร?
มันถูกเปิดตัวครั้งแรกใน Java 7 และแนวคิดทั้งหมดที่อยู่เบื้องหลังคือนักพัฒนาไม่จำเป็นต้องกังวลเกี่ยวกับการจัดการทรัพยากรสำหรับทรัพยากรที่ใช้ในบล็อก try-catch-final เพียงบล็อกเดียว สิ่งนี้ทำได้โดยการขจัดความจำเป็นใน การบล็อก ในที่สุดซึ่งนักพัฒนาใช้เพื่อปิดทรัพยากรในทางปฏิบัติเท่านั้น
ใน Java คำสั่ง try-with-resources เป็นคำสั่ง try ที่ประกาศทรัพยากรตั้งแต่หนึ่งรายการขึ้นไป ทรัพยากรเป็นวัตถุที่ต้องปิดหลังจากจบโปรแกรม เมื่อการดำเนินการออกจาก บล็อก try-with-resourcesทรัพยากรใดๆ ที่เปิดภายใน บล็อก try-with-resourcesจะถูกปิดโดยอัตโนมัติ โดยไม่คำนึงว่าจะมีข้อยกเว้นใดๆ เกิดขึ้นจากภายใน block try-with-resourcesหรือเมื่อพยายามปิด ทรัพยากร
หากต้องการใช้คุณลักษณะภาษาแบบลองกับทรัพยากรของ Java ให้ใช้กฎต่อไปนี้:
- ออบเจ็กต์ทั้งหมดที่ได้รับการจัดการโดยคำสั่ง try ด้วยทรัพยากรจะต้องใช้อินเตอร์เฟส AutoCloseable
- สามารถสร้างวัตถุ AutoCloseable หลายรายการได้ภายในบล็อก try with resource ของ Java
- อ็อบเจกต์ที่ประกาศในคำสั่ง try ด้วยรีซอร์สมีขอบเขตภายในบล็อกการลอง แต่ไม่ใช่การดักจับและบล็อกสุดท้าย
- วิธีการปิด () ของวัตถุที่ประกาศในการพยายามบล็อกทรัพยากรถูกเรียกใช้โดยไม่คำนึงว่าจะมีข้อยกเว้นเกิดขึ้นระหว่างการดำเนินการหรือไม่
- หากมีการโยนข้อยกเว้นในเมธอด close() ก็อาจได้รับการจัดหมวดหมู่เป็นข้อยกเว้นที่ถูกระงับ
ทรัพยากรที่อ้างอิงโดยวัตถุ AutoCloseable จะถูกปิดเสมอ ถ้ามีการใช้คำสั่ง try with Resources และการรั่วไหลของหน่วยความจำที่อาจเกิดขึ้นซึ่งมักเกิดจากการจัดสรรทรัพยากรอย่างไม่ถูกต้องจะถูกกำจัด
ไวยากรณ์
try(declare resources here) {
// use resources
}
catch(FileNotFoundException e) {
// exception handling
}
พูดง่ายๆ ก็คือ หากต้องการปิดอัตโนมัติ ทรัพยากรจะต้องมีทั้งการประกาศและเริ่มต้นภายในการลอง :
try (PrintWriter writer = new PrintWriter(new File("test.txt"))) {
writer.println("Hello World");
}
วิธีที่ง่ายและชัดเจนในการใช้ ฟังก์ชัน try-with-resources ใหม่ คือการแทนที่บล็อกtry -catch-final แบบดั้งเดิมและละเอียด
ลองเปรียบเทียบตัวอย่างโค้ดต่อไปนี้
บล็อก แรกคือ บล็อก try-catch-end ทั่วไป :
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();
}
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy
try (Scanner scanner = new Scanner(new File("test.txt"))) {
while (scanner.hasNext()) {
System.out.println(scanner.nextLine());
}
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
}
เมื่อพูดถึงข้อยกเว้น จะมีความแตกต่างใน การบล็อก try-catch-finalและบล็อก try-with-resources หากมีการโยนข้อยกเว้นในบล็อกลองและบล็อกสุดท้าย เมธอดจะส่งกลับข้อยกเว้นในบล็อกสุดท้าย
สำหรับ try-with-resources หากเกิดข้อยกเว้นในบล็อก try และในคำสั่ง try-with-resources เมธอดจะส่งกลับข้อยกเว้นที่เกิดใน try block ข้อยกเว้นที่เกิดจาก try-with-resources ถูกระงับ กล่าวคือ เราสามารถพูดได้ว่า block try-with-resources นั้นแสดงข้อยกเว้นที่ถูกระงับ
เหตุใดฉันจึงต้องใช้คำสั่ง try-with-resource
คำสั่ง try-with-resources ช่วยให้แน่ใจว่าทรัพยากรแต่ละรายการถูก ปิดเมื่อสิ้นสุดการดำเนินการคำสั่ง หากเราไม่ปิดทรัพยากร อาจก่อให้เกิดการรั่วไหลของทรัพยากร และโปรแกรมอาจทำให้ทรัพยากรที่มีอยู่หมดลงได้ นั่นคือสิ่งที่เกิดขึ้นส่วนใหญ่เมื่อคุณใช้try-catch-finally block
ก่อนหน้า Java SE 7 คุณสามารถใช้ บล็อก สุดท้ายเพื่อให้แน่ใจว่ารีซอร์สถูกปิด โดยไม่คำนึงว่า คำสั่ง tryจะเสร็จสมบูรณ์ตามปกติหรือทันทีทันใด ตัวอย่างต่อไปนี้ใช้ บล็อก สุดท้ายแทน คำสั่ง try -with-resources:
static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr);
try {
return br.readLine();
} finally {
br.close();
fr.close();
}
}
ในตัวอย่างนี้ หาก เมธอด readLineแสดงข้อยกเว้น และคำสั่งbr.close()ใน บล็อก สุดท้ายแสดงข้อยกเว้น แสดงว่าFileReaderรั่วไหล ดังนั้น ให้ใช้ คำสั่ง try -with-resources แทน การบล็อก สุดท้ายเพื่อปิดทรัพยากรของโปรแกรมของคุณ
ตัวอย่าง
ตัวอย่างต่อไปนี้อ่านบรรทัดแรกจากไฟล์ ใช้อินสแตนซ์ของFileReaderและBufferedReaderเพื่ออ่านข้อมูลจากไฟล์ FileReaderและBufferedReaderเป็นทรัพยากรที่ต้องปิดหลังจากโปรแกรมทำงานเสร็จแล้ว:
import java.io.*;
class Main {
public static void main(String[] args) {
String line;
try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
while ((line = br.readLine()) != null) {
System.out.println("Line =>"+line);
}
} catch (IOException e) {
System.out.println("IOException in try block =>" + e.getMessage());
}
}
}
ข้อยกเว้นที่ถูกระงับ
ถ้าบล็อกการลองแสดงข้อยกเว้น และข้อผิดพลาดอย่างน้อยหนึ่งข้อเกิดขึ้นจากความพยายามด้วยทรัพยากร ข้อยกเว้นที่เกิดจากความพยายามด้วยทรัพยากรจะถูกระงับ กล่าวอีกนัยหนึ่ง เราสามารถพูดได้ว่า ข้อยกเว้นซึ่งเกิดจาก try-with-resources ถูกระงับข้อยกเว้น
คุณสามารถรับข้อยกเว้นเหล่านี้ได้โดยใช้เมธอด getSuppress() ของคลาส Throwable
ตัวอย่าง :
ในตัวอย่างข้างต้น ข้อยกเว้นสามารถเกิดขึ้นได้จาก คำสั่ง try-with-resourcesเมื่อ:
- ไม่พบไฟล์test.txt
- การปิดวัตถุBufferedReader
หากเกิดข้อยกเว้นจากทั้ง บล็อก tryและคำสั่ง t ry-with-resourcesข้อยกเว้นจาก บล็อก tryจะถูกโยนทิ้ง และข้อยกเว้นจาก คำสั่ง try-with-resourcesจะถูกระงับ
การดึงข้อยกเว้นที่ถูกระงับ
ใน Java 7 และใหม่กว่า สามารถเรียกคืนข้อยกเว้นที่ถูกระงับได้โดยการเรียก เมธอด Throwable.getSuppressed()จากข้อยกเว้นที่โยนโดยบล็อกtry
getSuppress()ส่งคืนอาร์เรย์ที่มีข้อยกเว้นทั้งหมดซึ่งถูกระงับโดยคำสั่ง try-with-resources ถ้าไม่มีการระงับข้อยกเว้นหรือการยับยั้งถูกปิดใช้งาน อาร์เรย์ว่างจะถูกส่งกลับ
เราได้รับข้อยกเว้นที่ถูกระงับในcatch block
catch(IOException e) {
System.out.println("Thrown exception=>" + e.getMessage());
Throwable[] suppressedExceptions = e.getSuppressed();
for (int i=0; i<suppressedExceptions.length; i++) {
System.out.println("Suppressed exception=>" + suppressedExceptions[i]);
}
}
นี่คือข้อดีของการใช้ทรัพยากรแบบลอง:
- โค้ดที่อ่านได้มากขึ้นและง่ายต่อการเขียน
- การจัดการทรัพยากรอัตโนมัติ
- จำนวนบรรทัดของโค้ดลดลง
- เมื่อมีการเปิดทรัพยากรหลายรายการในการลองด้วยทรัพยากร ทรัพยากรนั้นจะปิดในลำดับที่กลับกันเพื่อหลีกเลี่ยงปัญหาการขึ้นต่อกัน
ก่อนที่ Java 7 จะแนะนำฟีเจอร์นี้ เราต้องใช้ บล็อก สุดท้ายเพื่อให้แน่ใจว่ารีซอร์สถูกปิดเพื่อหลีกเลี่ยงการรั่วไหลของรีซอร์ส
นี่คือโปรแกรมที่คล้ายกับตัวอย่างที่ 1 อย่างไรก็ตาม ในโปรแกรมนี้ เราได้ใช้บล็อกสุดท้ายเพื่อปิดทรัพยากร
ตัวอย่าง : ปิดทรัพยากรโดยใช้บล็อกสุดท้าย
import java.io.*;
class Main {
public static void main(String[] args) {
BufferedReader br = null;
String line;
try {
System.out.println("Entering try block");
br = new BufferedReader(new FileReader("test.txt"));
while ((line = br.readLine()) != null) {
System.out.println("Line =>"+line);
}
} catch (IOException e) {
System.out.println("IOException in try block =>" + e.getMessage());
} finally {
System.out.println("Entering finally block");
try {
if (br != null) {
br.close();
}
} catch (IOException e) {
System.out.println("IOException in finally block =>"+e.getMessage());
}
}
}
}
Entering try block
Line =>line from test.txt file
Entering finally block
สังเกตการลอง…จับบล็อกใน บล็อก สุดท้ายด้วยหรือไม่ นี่เป็นเพราะIOExceptionสามารถเกิดขึ้นได้ในขณะที่ปิด อินสแตนซ์ BufferedReaderภายใน บล็อก สุดท้าย นี้ ดังนั้นจึงถูกจับและจัดการได้เช่นกัน
คำสั่งtry-with-resources จัดการทรัพยากรโดยอัตโนมัติ เราไม่จำเป็นต้องปิดทรัพยากรอย่างชัดเจน เนื่องจาก JVM จะปิดทรัพยากรเหล่านั้นโดยอัตโนมัติ สิ่งนี้ทำให้โค้ดอ่านง่ายขึ้นและเขียนได้ง่ายขึ้น
ลองใช้ทรัพยากรด้วยทรัพยากรที่หลากหลาย
เราสามารถประกาศทรัพยากรหลายรายการได้ดีใน บล็อก try-with-resourcesโดยคั่นด้วยเครื่องหมายอัฒภาค:
try (Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
while (scanner.hasNext()) {
writer.print(scanner.nextLine());
}
}
ก่อน Java 9 เราสามารถใช้ตัวแปรใหม่ภายใน บล็อก try-with-resources เท่านั้น :
try (Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
// omitted
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy
final Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))
try (scanner;writer) {
// omitted
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy
ดังที่แสดงไว้ด้านบน ตัวแปร สแกนเนอร์ได้รับการประกาศ อย่างชัดแจ้ง ในขั้นสุดท้ายดังนั้นเราจึงสามารถใช้กับบล็อกtry-with-resources แม้ว่า ตัวแปร ตัวเขียนจะยังไม่เป็นที่สิ้นสุดอย่างชัดเจน แต่จะไม่เปลี่ยนแปลงหลังจากการมอบหมายครั้งแรก ดังนั้น เราสามารถใช้ ตัวแปร ตัวเขียนได้เช่นกัน
มีความสุขในการเรียนรู้
เข้าร่วมกลุ่ม Mouad Oumous Java WhatsApp เข้าร่วม
เข้าร่วม Mouad Oumous Telegram Channel เข้าร่วม
สนับสนุนสิ่งพิมพ์ของเราโดยติดตาม
คำแนะนำเกี่ยวกับการแมปวัตถุด้วย ModelMapper ใน Java เริ่มต้นใช้งาน Spring Boot: บทช่วยสอนที่ครอบคลุมสำหรับผู้เริ่มต้น ความปลอดภัยของ Spring Boot | สปส. | OAuth2 กับ Okta คำถามสัมภาษณ์ตามสตรีม Java8 ที่พบบ่อยที่สุด - ส่วนที่ 2 การเข้ารหัส: แผ่อาร์เรย์ใน Javascript คำถามสัมภาษณ์ตามสตรีม Java8 ที่พบบ่อยที่สุด - ตอนที่ 1




































![รายการที่เชื่อมโยงคืออะไร? [ส่วนที่ 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)