ในชีวิตประจำวันบางครั้งมีสถานการณ์เกิดขึ้นโดยที่เราไม่ได้วางแผนไว้ ตัวอย่างเช่น คุณตื่นไปทำงานในตอนเช้า มองหาที่ชาร์จสำหรับโทรศัพท์ของคุณ แต่ไม่มีเลย คุณไปห้องน้ำเพื่อล้างหน้า - น้ำปิดแล้ว ขึ้นรถแล้วสตาร์ทไม่ติด แต่บุคคลสามารถรับมือกับสถานการณ์ที่ไม่คาดฝันดังกล่าวได้อย่างง่ายดาย เราจะพยายามค้นหาว่าโปรแกรม Java จัดการกับพวกมันอย่างไรในบทความนี้
Java มีข้อยกเว้นอะไรบ้าง
ในโลกของการเขียนโปรแกรม การเกิดข้อผิดพลาดและสถานการณ์ที่ไม่คาดคิดระหว่างการทำงานของโปรแกรมเรียกว่าข้อยกเว้น ในโปรแกรม ข้อยกเว้นอาจเกิดขึ้นอันเป็นผลมาจากการกระทำของผู้ใช้ที่ไม่ถูกต้อง การขาดทรัพยากรที่จำเป็นบนดิสก์ หรือการสูญเสียการเชื่อมต่อกับเซิร์ฟเวอร์ผ่านเครือข่าย ข้อยกเว้นระหว่างการทำงานของโปรแกรมอาจเกิดจากข้อผิดพลาดในการเขียนโปรแกรมหรือการใช้ API ที่ไม่ถูกต้อง ต่างจากโลกของเรา โปรแกรมต้องรู้ชัดเจนว่าต้องทำอย่างไรในสถานการณ์เช่นนี้ Java จัดเตรียมกลไกข้อยกเว้นเพื่อจุดประสงค์นี้
สั้น ๆ เกี่ยวกับคำหลัก try, catch, ในที่สุด, พ่น
การจัดการข้อยกเว้นใน Java ขึ้นอยู่กับการใช้คีย์เวิร์ดต่อไปนี้ในโปรแกรม:
- ลอง - กำหนดบล็อกของโค้ดที่อาจเกิดข้อยกเว้น
- catch – กำหนดบล็อกของโค้ดที่ใช้จัดการข้อยกเว้น
- สุดท้าย – กำหนดบล็อกของโค้ดที่เป็นทางเลือก แต่ถ้ามีอยู่ ก็จะดำเนินการต่อไป โดยไม่คำนึงถึงผลลัพธ์ของบล็อกลอง
คำหลักเหล่านี้ใช้เพื่อสร้างโครงสร้างการประมวลผลพิเศษในโค้ดโปรแกรม: try{}catch, try{}catch{}finally, try{}finally{}
- โยน - ใช้เพื่อยกข้อยกเว้น;
- พ่น - ใช้ในลายเซ็นวิธีการเพื่อเตือนว่าวิธีการนี้อาจส่งข้อยกเว้น
ตัวอย่างการใช้คีย์เวิร์ดในโปรแกรม Java:
public String input() throws MyException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String s = null;
try {
s = reader.readLine();
} catch (IOException e) {
System.out.println(e.getMessage());
} finally {
try {
reader.close();
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
if (s.equals("")) {
throw new MyException("String can not be empty!");
}
return s;
}
เหตุใดเราจึงต้องมีกลไกข้อยกเว้น
ลองดูตัวอย่างในโลกแห่งความเป็นจริง ลองจินตนาการว่ามีส่วนบนทางหลวงที่มีสะพานฉุกเฉินซึ่งมีความจุจำกัด หากยานพาหนะที่มีมวลเกินขีดความสามารถในการรองรับของสะพานขับข้าม สะพานนั้นอาจพังทลาย และสถานการณ์สำหรับผู้ขับขี่อาจพูดง่ายๆ ได้ว่าเป็นเรื่องพิเศษ เพื่อป้องกันไม่ให้เกิดเหตุการณ์เช่นนี้ หน่วยงานบริการทางถนนจึงได้ติดตั้งป้ายเตือนบนถนนไว้ล่วงหน้า ผู้ขับขี่รถยนต์เมื่อดูป้ายเตือนจะเปรียบเทียบน้ำหนักรถกับน้ำหนักที่อนุญาตให้ขับบนสะพานได้ หากเกินกว่านั้นเขาจะอ้อม ต้องขอบคุณการบริการทางถนนที่ทำให้คนขับรถบรรทุกมีโอกาสเปลี่ยนเส้นทางล่วงหน้า ประการที่สอง เตือนอันตรายบนเส้นทางหลัก และสุดท้าย เตือนใช้ไม่ได้ สะพานภายใต้เงื่อนไขบางประการ
ความสามารถในการป้องกันและแก้ไขข้อยกเว้นในโปรแกรมเพื่อให้สามารถดำเนินการต่อได้คือหนึ่งในเหตุผลในการใช้ข้อยกเว้นใน Java กลไกข้อยกเว้นยังช่วยให้คุณปกป้องโค้ดที่คุณเขียน (อินเทอร์เฟซการเขียนโปรแกรม) จากการใช้ในทางที่ผิดโดยผู้ใช้โดยการตรวจสอบ (ตรวจสอบ) ข้อมูลขาเข้า ตอนนี้ขอเป็นตำรวจจราจรสักครู่ ขั้นแรกคุณควรทราบสถานที่ที่ผู้ขับขี่รถยนต์อาจประสบปัญหาได้ ประการที่สองต้องเตรียมและติดตั้งป้ายเตือน สุดท้ายต้องจัดให้มีเส้นทางเบี่ยงในกรณีเกิดอันตรายบนเส้นทางหลัก ใน Java กลไกข้อยกเว้นทำงานในลักษณะเดียวกัน ในขั้นตอนการพัฒนาโปรแกรม เราจะ "ปกป้อง" ส่วนที่เป็นอันตรายของโค้ดจากข้อยกเว้นโดยใช้บล็อก try{} จัดเตรียมเส้นทาง "สำรอง" โดยใช้บล็อก catch{} และในบล็อกสุดท้าย {} เราจะเขียนโค้ดที่ถูกเรียกใช้งานใน โปรแกรมสำหรับผลลัพธ์ใด ๆ ในกรณีที่เราไม่สามารถให้ "เส้นทางฉุกเฉิน" หรือจงใจต้องการปล่อยให้ผู้ใช้เลือก อย่างน้อยเราต้องเตือนเขาถึงอันตราย ทำไม ลองนึกภาพความขุ่นเคืองของคนขับที่จะไปถึงสะพานฉุกเฉินที่ไม่สามารถขับข้ามไปได้โดยไม่เจอป้ายเตือนแม้แต่ป้ายเดียวตลอดทาง! ในการเขียนโปรแกรม เมื่อเขียนคลาสและวิธีการของเรา เราไม่สามารถคาดการณ์บริบทการใช้งานโดยนักพัฒนารายอื่นในโปรแกรมของพวกเขาได้เสมอไป ดังนั้นเราจึงไม่สามารถคาดการณ์เส้นทางที่ถูกต้อง 100% เพื่อแก้ไขสถานการณ์ข้อยกเว้นได้ ในเวลาเดียวกัน ถือเป็นแนวปฏิบัติที่ดีที่จะเตือนผู้ใช้เกี่ยวกับโค้ดของเราเกี่ยวกับความเป็นไปได้ที่จะมีข้อยกเว้น กลไกข้อยกเว้นของ Java ช่วยให้เราทำสิ่งนี้ได้โดยใช้การโยน ซึ่งเป็นการประกาศลักษณะการทำงานทั่วไปของวิธีการของเราในการส่งข้อยกเว้น ดังนั้นจึงปล่อยให้ผู้ใช้ใช้วิธีการเขียนโค้ดเพื่อจัดการข้อยกเว้นใน Java
คำเตือนเรื่อง "ปัญหา"
เมื่อคุณไม่ได้วางแผนที่จะจัดการกับข้อยกเว้นในวิธีการของคุณ แต่ต้องการเตือนผู้ใช้ถึงวิธีการเกี่ยวกับสถานการณ์ข้อยกเว้นที่เป็นไปได้ ให้ใช้คีย์เวิร์ด Throws คำสำคัญนี้ในลายเซ็นวิธีการหมายความว่าภายใต้เงื่อนไขบางประการวิธีการนั้นอาจมีข้อยกเว้น คำเตือนนี้เป็นส่วนหนึ่งของอินเทอร์เฟซของวิธีการ และให้สิทธิ์แก่ผู้ใช้ในการปรับแต่งการใช้งานตัวจัดการข้อยกเว้น หลังจากการพ่น เราจะระบุประเภทของข้อยกเว้นที่ถูกโยน โดยปกติแล้วสิ่งเหล่านี้จะ เป็นลูกหลานของ คลาส Java
Exception เนื่องจาก Java เป็นภาษาเชิงวัตถุ ข้อยกเว้นทั้งหมดใน Java จึงเป็นวัตถุ
ลำดับชั้นข้อยกเว้นของ Java
เมื่อเกิดข้อผิดพลาดระหว่างการทำงานของโปรแกรม รันไทม์ JVM จะสร้างอ็อบเจ็กต์ประเภทที่ต้องการจากลำดับชั้นข้อยกเว้นของ Java ซึ่งเป็นชุดของข้อยกเว้นที่เป็นไปได้ที่สืบทอดมาจาก "บรรพบุรุษ" ทั่วไป - คลาส Throwable สถานการณ์พิเศษที่เกิดขึ้นในโปรแกรมสามารถแบ่งออกเป็นสองกลุ่ม:
- สถานการณ์ที่ไม่สามารถฟื้นฟูการทำงานตามปกติของโปรแกรมต่อไปได้
- การกู้คืนเป็นไปได้
กลุ่มแรกประกอบด้วยสถานการณ์เมื่อมีข้อยกเว้นที่สืบทอดมาจาก คลาส
Error เกิด ขึ้น สิ่งเหล่านี้เป็นข้อผิดพลาดที่เกิดขึ้นระหว่างการทำงานของโปรแกรมอันเป็นผลมาจากความล้มเหลวของ JVM หน่วยความจำล้น หรือระบบล่ม มักจะบ่งบอกถึงปัญหาร้ายแรงที่ไม่สามารถแก้ไขได้โดยใช้ซอฟต์แวร์ ข้อยกเว้นประเภทนี้ใน Java ถูกจัดประเภทเป็นไม่ถูกตรวจสอบในขั้นตอนการคอมไพล์ กลุ่มนี้ยังรวมถึง RuntimeException - ข้อยกเว้น ผู้สืบทอดของ คลาส
Exceptionที่สร้างโดย JVM ระหว่างการทำงานของโปรแกรม มักเกิดจากข้อผิดพลาดในการเขียนโปรแกรม ข้อยกเว้นเหล่านี้จะไม่ถูกตรวจสอบในขณะคอมไพล์ ดังนั้นการเขียนโค้ดเพื่อจัดการจึงไม่จำเป็น กลุ่มที่สองประกอบด้วยสถานการณ์พิเศษที่มองเห็นได้ในขั้นตอนของการเขียนโปรแกรมและจะต้องเขียนโค้ดประมวลผล มีการตรวจสอบข้อยกเว้นดังกล่าว งานส่วนใหญ่ของนักพัฒนา Java เมื่อต้องรับมือกับข้อยกเว้นคือการจัดการสถานการณ์ดังกล่าว
การสร้างข้อยกเว้น
ในระหว่างการทำงานของโปรแกรม JVM จะส่งข้อยกเว้นหรือใช้ คำ สั่ง
Throw ด้วยตนเอง สิ่งนี้จะสร้างอ็อบเจ็กต์ข้อยกเว้นในหน่วยความจำและขัดจังหวะการทำงานของโค้ดโปรแกรมหลัก ในขณะที่ตัวจัดการข้อยกเว้น JVM พยายามค้นหาวิธีจัดการกับข้อยกเว้น
การจัดการข้อยกเว้น
การสร้างบล็อกโค้ดที่เราจัดให้มีการจัดการข้อยกเว้นใน Java เสร็จสิ้นในโปรแกรมโดยใช้โครงสร้าง try{}catch, try{}catch{}finally, try{}finally{}
เมื่อมีการยกข้อยกเว้นขึ้นในบล็อก try ตัวจัดการข้อยกเว้นจะถูกค้นหาในบล็อก catch ต่อไปนี้ หาก catch มีตัวจัดการสำหรับข้อยกเว้นประเภทนี้ การควบคุมจะส่งผ่านไป ถ้าไม่เช่นนั้น JVM จะค้นหาตัวจัดการสำหรับประเภทข้อยกเว้นนั้นในสายการเรียกเมธอดจนกว่าจะพบการจับที่เหมาะสม หลังจากดำเนินการ catch block แล้ว การควบคุมจะถูกส่งผ่านไปยังตัวเลือกบล็อก
ในที่สุด หากไม่พบบล็อก catch ที่เหมาะสม JVM จะหยุดการทำงานของโปรแกรมและแสดงสแต็กของการเรียกเมธอด -
stack Traceโดยก่อนหน้านี้ได้ดำเนินการโค้ดบล็อกสุดท้ายแล้ว ถ้ามี ตัวอย่างการจัดการข้อยกเว้น:
public class Print {
void print(String s) {
if (s == null) {
throw new NullPointerException("Exception: s is null!");
}
System.out.println("Inside method print: " + s);
}
public static void main(String[] args) {
Print print = new Print();
List list= Arrays.asList("first step", null, "second step");
for (String s:list) {
try {
print.print(s);
}
catch (NullPointerException e) {
System.out.println(e.getMessage());
System.out.println("Exception was processed. Program continues");
}
finally {
System.out.println("Inside bloсk finally");
}
System.out.println("Go program....");
System.out.println("-----------------");
}
}
}
ผลลัพธ์ของ วิธีการ
หลัก :
Inside method print: first step
Inside bloсk finally
Go program....
-----------------
Exception: s is null!
Exception was processed. Program continues
Inside bloсk finally
Go program....
-----------------
Inside method print: second step
Inside bloсk finally
Go program....
-----------------
โดยปกติแล้ว บล็อกนี้
finally
ใช้เพื่อปิดสตรีมที่เปิดในบล็อกลองหรือเปิดทรัพยากรให้ว่าง อย่างไรก็ตาม เมื่อเขียนโปรแกรม ไม่สามารถติดตามการปิดทรัพยากรทั้งหมดได้เสมอไป เพื่อให้ชีวิตของเราง่ายขึ้น นักพัฒนา Java ได้เสนอโครงสร้าง
try-with-resources
ที่จะปิดทรัพยากรที่เปิดในบล็อก try โดยอัตโนมัติ ตัวอย่างแรกของเราสามารถเขียนใหม่ได้ดังนี้
try-with-resources
:
public String input() throws MyException {
String s = null;
try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))){
s = reader.readLine();
} catch (IOException e) {
System.out.println(e.getMessage());
}
if (s.equals("")){
throw new MyException ("String can not be empty!");
}
return s;
}
ด้วยความสามารถของ Java ตั้งแต่เวอร์ชัน 7 เป็นต้นไป เราจึงสามารถรวมการจับข้อยกเว้นประเภทต่างๆ ไว้ในบล็อกเดียว ทำให้โค้ดมีขนาดกะทัดรัดและอ่านง่ายขึ้น ตัวอย่างเช่น:
public String input() {
String s = null;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) {
s = reader.readLine();
if (s.equals("")) {
throw new MyException("String can not be empty!");
}
} catch (IOException | MyException e) {
System.out.println(e.getMessage());
}
return s;
}
ผลลัพธ์
การใช้ข้อยกเว้นใน Java ช่วยให้เราสามารถเพิ่มความทนทานต่อข้อบกพร่องของโปรแกรมผ่านการใช้เส้นทาง "สำรอง" เพื่อแยกตรรกะของโค้ดหลักออกจากโค้ดการจัดการข้อยกเว้นผ่านการใช้ catch block และยังช่วยให้เรา โอกาสในการมอบหมายการจัดการข้อยกเว้นให้กับผู้ใช้โค้ดของเราโดยใช้การพ่น
GO TO FULL VERSION