สวัสดี! ในบทเรียนที่แล้ว เราได้ทำความคุ้นเคยกับข้อยกเว้นในภาษา Java และดูตัวอย่างวิธีการทำงานกับข้อยกเว้นเหล่านั้น วันนี้เราจะมาดูโครงสร้างของข้อยกเว้นอย่างลึกซึ้งยิ่งขึ้น และเรียนรู้วิธีการเขียนข้อยกเว้นของเราเอง :)
ประเภทของข้อยกเว้น
อย่างที่เราพูดไปก่อนหน้านี้ มีข้อยกเว้นมากมายใน Java เกือบ 400 รายการ! แต่พวกเขาทั้งหมดถูกแบ่งออกเป็นกลุ่ม ดังนั้นจึงค่อนข้างง่ายที่จะจดจำพวกเขา นี่คือลักษณะ: ข้อยกเว้นทั้งหมดมีบรรพบุรุษร่วมกันในThrowable
ชั้นเรียน สองกลุ่มหลักได้มาจาก: ข้อยกเว้น ( ข้อยกเว้น ) และข้อผิดพลาด ( ข้อผิดพลาด ) ข้อผิดพลาด - สิ่งนี้แสดงถึงข้อผิดพลาดรันไทม์ที่สำคัญที่เกี่ยวข้องกับการทำงานของเครื่องเสมือน Java ในกรณีส่วนใหญ่ ไม่จำเป็นต้องจัดการ Error เนื่องจากเป็นการบ่งชี้ข้อบกพร่องร้ายแรงบางอย่างในโค้ด ที่มีชื่อเสียงที่สุดคือStackOverflowError (สิ่งนี้เกิดขึ้นเมื่อเมธอดเรียกตัวเองว่าไม่รู้จบ) และOutOfMemoryError(สิ่งนี้เกิดขึ้นเมื่อมีหน่วยความจำไม่เพียงพอที่จะสร้างวัตถุใหม่) อย่างที่คุณเห็น ในสถานการณ์เหล่านี้ มักจะไม่มีอะไรต้องจัดการเลยในขณะรันไทม์: โค้ดถูกเขียนอย่างไม่ถูกต้องและจำเป็นต้องทำใหม่ ข้อยกเว้น - สิ่งนี้แสดงถึงข้อยกเว้น: สถานการณ์พิเศษที่ไม่ได้วางแผนซึ่งเกิดขึ้นในขณะที่โปรแกรมกำลังทำงาน สิ่งเหล่านี้ไม่ร้ายแรงเท่าข้อผิดพลาด แต่ก็ยังต้องการความสนใจจากเรา ข้อยกเว้นทั้งหมดแบ่งออกเป็น 2 ประเภท: ตรวจสอบและยกเลิกการเลือก ข้อยกเว้นที่ตรวจสอบทั้งหมดได้มาจากException
คลาส "ตรวจสอบ" หมายถึงอะไร? เราได้พูดถึงเรื่องนี้ในบทเรียนที่แล้ว: "ดังนั้น คอมไพเลอร์ Java จึงรู้ข้อยกเว้นที่พบบ่อยที่สุดและสถานการณ์ที่อาจเกิดขึ้น" ตัวอย่างเช่น มันรู้ว่าถ้าโค้ดอ่านข้อมูลจากไฟล์ ไฟล์นั้นก็จะไม่มีอยู่โดยง่าย และมีสถานการณ์เช่นนี้มากมาย (ซึ่งสามารถอนุมานได้) ดังนั้น คอมไพเลอร์จะตรวจสอบโค้ดของเราล่วงหน้าเพื่อดูว่ามีข้อยกเว้นที่อาจเกิดขึ้นเหล่านี้หรือไม่ หากพบโค้ดเหล่านี้ โค้ดจะไม่คอมไพล์จนกว่าเราจะจัดการหรือโยนโค้ดใหม่อีกครั้ง ข้อยกเว้นประเภทที่สองคือ "ไม่เลือก" พวกเขาได้รับมาจากRuntimeException
ชั้นเรียน แตกต่างจากข้อยกเว้นที่ตรวจสอบอย่างไร ดูเหมือนว่ายังมีคลาสต่างๆ มากมายที่ได้มาจากRuntimeException
(ซึ่งอธิบายข้อยกเว้นรันไทม์) ข้อแตกต่างคือคอมไพเลอร์ไม่คาดว่าจะเกิดข้อผิดพลาดเหล่านี้ ดูเหมือนว่าจะพูดว่า "ตอนที่เขียนโค้ด ฉันไม่พบอะไรที่น่าสงสัย แต่มีบางอย่างผิดพลาดในขณะที่รัน เห็นได้ชัดว่ามีข้อผิดพลาดในโค้ด!" และนี่คือความจริง ข้อยกเว้นที่ไม่ได้ตรวจสอบมักเกิดจากข้อผิดพลาดของโปรแกรมเมอร์ และเห็นได้ชัดว่าคอมไพเลอร์ไม่สามารถคาดการณ์ถึงสถานการณ์เลวร้ายที่เป็นไปได้ทุกอย่างที่ผู้คนอาจสร้างขึ้นด้วยมือของพวกเขาเอง :) ดังนั้นจึงไม่ตรวจสอบว่ามีการจัดการข้อยกเว้นดังกล่าวในโค้ดของเราหรือไม่ คุณพบข้อยกเว้นที่ไม่ได้ตรวจสอบหลายรายการแล้ว:
- ArithmeticExceptionเกิดขึ้นเมื่อหารด้วยศูนย์
- ArrayIndexOutOfBoundsExceptionเกิดขึ้นเมื่อคุณพยายามเข้าถึงตำแหน่งนอกอาร์เรย์
try-catch
บล็อกเพื่อตรวจสอบว่าคุณหารด้วยศูนย์โดยบังเอิญหรือไม่? ทุกครั้งที่คุณเข้าถึงอาร์เรย์ คุณจะต้องเขียนtry-catch
บล็อกเพื่อตรวจสอบว่าดัชนีของคุณอยู่นอกขอบเขตหรือไม่ ทุกอย่างจะเป็นรหัสสปาเก็ตตี้และไม่สามารถอ่านได้ทั้งหมด มันสมเหตุสมผลแล้วที่ความคิดนี้ถูกล้มเลิกไป ด้วยเหตุนี้ ข้อยกเว้นที่ไม่ได้ตรวจสอบจึงไม่จำเป็นต้องจัดการในtry-catch
บล็อกหรือโยนใหม่ (แม้ว่าจะเป็นไปได้ในทางเทคนิค เช่นเดียวกับข้อผิดพลาด)
วิธีโยนข้อยกเว้นของคุณเอง
แน่นอน ผู้สร้างของ Java ไม่สามารถคาดเดาทุกสถานการณ์พิเศษที่อาจเกิดขึ้นในโปรแกรม มีโปรแกรมมากมายในโลกนี้และมีความหลากหลายมากเกินไป แต่นี่ไม่ใช่เรื่องที่ต้องกังวล เพราะคุณสามารถสร้างข้อยกเว้นของคุณเองได้หากจำเป็น นี้ง่ายมากที่จะทำ สิ่งที่คุณต้องทำคือสร้างชั้นเรียนของคุณเอง คุณควรแน่ใจว่าชื่อของมันลงท้ายด้วย "Exception" คอมไพเลอร์ไม่ต้องการสิ่งนี้ แต่โปรแกรมเมอร์คนอื่นๆ ที่อ่านโค้ดของคุณจะเข้าใจทันทีว่าเป็นคลาสยกเว้น นอกจากนี้ ระบุว่าคลาสสืบทอดมาจากException
คลาส (คอมไพเลอร์ไม่ต้องการสิ่งนี้) ตัวอย่างเช่น สมมติว่าเรามีDog
ชั้นเรียน เราสามารถพาสุนัขไปเดินเล่นโดยใช้walk()
วิธี. แต่ก่อนที่จะทำเช่นนั้น เราต้องตรวจสอบว่าสัตว์เลี้ยงของเราสวมปลอกคอ สายจูง และปากกระบอกปืนหรือไม่ หากอุปกรณ์นี้ขาดหายไป เราจะส่งข้อยกเว้นของเราเอง: DogIsNotReadyException รหัสของมันมีลักษณะดังนี้:
public class DogIsNotReadyException extends Exception {
public DogIsNotReadyException(String message) {
super(message);
}
}
เพื่อระบุว่าคลาสนั้นเป็นข้อยกเว้น คุณต้องเขียน " ขยายข้อยกเว้น " ตามหลังชื่อคลาส (ซึ่งหมายถึง "คลาสนั้นมาจากคลาสข้อยกเว้น") ในคอนสตรัคเตอร์ เราเพียงแค่เรียกException
คลาสคอนสตรัคเตอร์ด้วยข้อความ สตริง (หากเกิดข้อยกเว้น เราจะแสดงข้อความ คำอธิบายข้อผิดพลาด แก่ผู้ใช้) นี่คือลักษณะของสิ่งนี้ในรหัสชั้นเรียนของเรา:
public class Dog {
String name;
boolean isCollarPutOn;
boolean isLeashPutOn;
boolean isMuzzlePutOn;
public Dog(String name) {
this.name = name;
}
public static void main(String[] args) {
}
public void putCollar() {
System.out.println("The collar is on!");
this.isCollarPutOn = true;
}
public void putLeash() {
System.out.println("The leash is on!");
this.isLeashPutOn = true;
}
public void putMuzzle() {
System.out.println("The muzzle is on!");
this.isMuzzlePutOn = true;
}
public void walk() throws DogIsNotReadyException {
System.out.println("We're getting ready for a walk!");
if (isCollarPutOn && isLeashPutOn && isMuzzlePutOn) {
System.out.println("Hooray, let's go for a walk! " + name + " is very happy!");
} else {
throw new DogIsNotReadyException(name + " is not ready for a walk! Check the gear!");
}
}
}
ตอน นี้ วิธีการ ของเราwalk()
โยนDogIsNotReadyException สิ่งนี้ทำได้ด้วยการโยนคำหลัก ดังที่เราได้กล่าวไว้ก่อนหน้านี้ ข้อยกเว้นคือวัตถุ ดังนั้น เมื่อมีข้อยกเว้นเกิดขึ้น (สุนัขขาดบางสิ่งไป) ในวิธีการของเรา เราจะสร้างวัตถุใหม่DogIsNotReadyException
และโยนมันโดยใช้คีย์เวิร์ด Throw เราเพิ่ม " โยน DogIsNotReadyException " ในการประกาศเมธอด กล่าวอีกนัยหนึ่ง ตอนนี้คอมไพเลอร์ทราบว่าการเรียกใช้walk()
เมธอดอาจกลายเป็นสถานการณ์พิเศษได้ ดังนั้น ข้อยกเว้นนี้ต้องได้รับการจัดการหากเราเรียกวิธีนี้ในโปรแกรมของเรา ลองทำวิธีนี้ดูmain()
:
public static void main(String[] args) {
Dog dog = new Dog("Buddy");
dog.putCollar();
dog.putMuzzle();
dog.walk();// Unhandled exception: DogIsNotReadyException
}
สิ่งนี้จะไม่รวบรวม ข้อยกเว้นไม่ได้รับการจัดการ! เรารวมรหัสของเราไว้ในtry-catch
บล็อกเพื่อจัดการกับข้อยกเว้น:
public static void main(String[] args) {
Dog dog = new Dog("Buddy");
dog.putCollar();
dog.putMuzzle();
try {
dog.walk();
} catch (DogIsNotReadyException e) {
System.out.println(e.getMessage());
System.out.println("Checking the gear! Is the collar on? " + dog.isCollarPutOn + "\r\n Is the leash on? "
+ dog.isLeashPutOn + "\r\n Is the muzzle on? " + dog.isMuzzlePutOn);
}
}
ทีนี้มาดูที่เอาต์พุตของคอนโซล: ปลอกคอเปิดอยู่! ปากกระบอกปืนเปิดอยู่! เรากำลังเตรียมตัวไปเดินเล่นกัน! บัดดี้ไม่พร้อมเดิน! เช็คเกียร์! เช็คเกียร์! ปลอกคออยู่หรือเปล่า? สายจูงเปิดอยู่หรือไม่? เท็จ เปิดปากกระบอกปืนหรือไม่? จริง ดูว่าเอาต์พุตของคอนโซลมีข้อมูลมากขึ้นเพียงใด! เราเห็นทุกขั้นตอนในโปรแกรม เราเห็นว่าข้อผิดพลาดเกิดขึ้นที่ใด และเรายังสามารถเห็นได้ทันทีว่าสุนัขของเราขาดอะไรไป :) และนั่นคือวิธีที่คุณสร้างข้อยกเว้นของคุณเอง อย่างที่คุณเห็น ไม่มีอะไรซับซ้อนเกี่ยวกับเรื่องนี้ และแม้ว่าผู้สร้างของ Java จะไม่สนใจที่จะรวมข้อยกเว้นพิเศษสำหรับสุนัขที่มีอุปกรณ์ครบครันไว้ในภาษานี้ แต่เราได้แก้ไขการกำกับดูแลของพวกเขาแล้ว :)
อ่านเพิ่มเติม: |
---|
GO TO FULL VERSION