CodeGym /จาวาบล็อก /สุ่ม /ข้อยกเว้น: ทำเครื่องหมาย ไม่เลือก และกำหนดเอง
John Squirrels
ระดับ
San Francisco

ข้อยกเว้น: ทำเครื่องหมาย ไม่เลือก และกำหนดเอง

เผยแพร่ในกลุ่ม
สวัสดี! ในบทเรียนที่แล้ว เราได้ทำความคุ้นเคยกับข้อยกเว้นในภาษา Java และดูตัวอย่างวิธีการทำงานกับข้อยกเว้นเหล่านั้น วันนี้เราจะมาดูโครงสร้างของข้อยกเว้นอย่างลึกซึ้งยิ่งขึ้น และเรียนรู้วิธีการเขียนข้อยกเว้นของเราเอง :)

ประเภทของข้อยกเว้น

อย่างที่เราพูดไปก่อนหน้านี้ มีข้อยกเว้นมากมายใน Java เกือบ 400 รายการ! แต่พวกเขาทั้งหมดถูกแบ่งออกเป็นกลุ่ม ดังนั้นจึงค่อนข้างง่ายที่จะจดจำพวกเขา นี่คือลักษณะ: ข้อยกเว้น: ทำเครื่องหมาย ไม่เลือก และกำหนดเอง - 2 ข้อยกเว้นทั้งหมดมีบรรพบุรุษร่วมกันในThrowableชั้นเรียน สองกลุ่มหลักได้มาจาก: ข้อยกเว้น ( ข้อยกเว้น ) และข้อผิดพลาด ( ข้อผิดพลาด ) ข้อผิดพลาด - สิ่งนี้แสดงถึงข้อผิดพลาดรันไทม์ที่สำคัญที่เกี่ยวข้องกับการทำงานของเครื่องเสมือน Java ในกรณีส่วนใหญ่ ไม่จำเป็นต้องจัดการ Error เนื่องจากเป็นการบ่งชี้ข้อบกพร่องร้ายแรงบางอย่างในโค้ด ที่มีชื่อเสียงที่สุดคือStackOverflowError (สิ่งนี้เกิดขึ้นเมื่อเมธอดเรียกตัวเองว่าไม่รู้จบ) และOutOfMemoryError(สิ่งนี้เกิดขึ้นเมื่อมีหน่วยความจำไม่เพียงพอที่จะสร้างวัตถุใหม่) อย่างที่คุณเห็น ในสถานการณ์เหล่านี้ มักจะไม่มีอะไรต้องจัดการเลยในขณะรันไทม์: โค้ดถูกเขียนอย่างไม่ถูกต้องและจำเป็นต้องทำใหม่ ข้อยกเว้น - สิ่งนี้แสดงถึงข้อยกเว้น: สถานการณ์พิเศษที่ไม่ได้วางแผนซึ่งเกิดขึ้นในขณะที่โปรแกรมกำลังทำงาน สิ่งเหล่านี้ไม่ร้ายแรงเท่าข้อผิดพลาด แต่ก็ยังต้องการความสนใจจากเรา ข้อยกเว้นทั้งหมดแบ่งออกเป็น 2 ประเภท: ตรวจสอบและยกเลิกการเลือก ข้อยกเว้น: ทำเครื่องหมาย ไม่เลือก และกำหนดเอง - 3 ข้อยกเว้นที่ตรวจสอบทั้งหมดได้มาจากExceptionคลาส "ตรวจสอบ" หมายถึงอะไร? เราได้พูดถึงเรื่องนี้ในบทเรียนที่แล้ว: "ดังนั้น คอมไพเลอร์ Java จึงรู้ข้อยกเว้นที่พบบ่อยที่สุดและสถานการณ์ที่อาจเกิดขึ้น" ตัวอย่างเช่น มันรู้ว่าถ้าโค้ดอ่านข้อมูลจากไฟล์ ไฟล์นั้นก็จะไม่มีอยู่โดยง่าย และมีสถานการณ์เช่นนี้มากมาย (ซึ่งสามารถอนุมานได้) ดังนั้น คอมไพเลอร์จะตรวจสอบโค้ดของเราล่วงหน้าเพื่อดูว่ามีข้อยกเว้นที่อาจเกิดขึ้นเหล่านี้หรือไม่ หากพบโค้ดเหล่านี้ โค้ดจะไม่คอมไพล์จนกว่าเราจะจัดการหรือโยนโค้ดใหม่อีกครั้ง ข้อยกเว้นประเภทที่สองคือ "ไม่เลือก" พวกเขาได้รับมาจากRuntimeExceptionชั้นเรียน แตกต่างจากข้อยกเว้นที่ตรวจสอบอย่างไร ดูเหมือนว่ายังมีคลาสต่างๆ มากมายที่ได้มาจากRuntimeException(ซึ่งอธิบายข้อยกเว้นรันไทม์) ข้อแตกต่างคือคอมไพเลอร์ไม่คาดว่าจะเกิดข้อผิดพลาดเหล่านี้ ดูเหมือนว่าจะพูดว่า "ตอนที่เขียนโค้ด ฉันไม่พบอะไรที่น่าสงสัย แต่มีบางอย่างผิดพลาดในขณะที่รัน เห็นได้ชัดว่ามีข้อผิดพลาดในโค้ด!" และนี่คือความจริง ข้อยกเว้นที่ไม่ได้ตรวจสอบมักเกิดจากข้อผิดพลาดของโปรแกรมเมอร์ และเห็นได้ชัดว่าคอมไพเลอร์ไม่สามารถคาดการณ์ถึงสถานการณ์เลวร้ายที่เป็นไปได้ทุกอย่างที่ผู้คนอาจสร้างขึ้นด้วยมือของพวกเขาเอง :) ดังนั้นจึงไม่ตรวจสอบว่ามีการจัดการข้อยกเว้นดังกล่าวในโค้ดของเราหรือไม่ คุณพบข้อยกเว้นที่ไม่ได้ตรวจสอบหลายรายการแล้ว:
  • ArithmeticExceptionเกิดขึ้นเมื่อหารด้วยศูนย์
  • ArrayIndexOutOfBoundsExceptionเกิดขึ้นเมื่อคุณพยายามเข้าถึงตำแหน่งนอกอาร์เรย์
แน่นอน คุณสามารถจินตนาการได้ว่าผู้สร้าง Java อาจแนะนำการจัดการข้อยกเว้นที่จำเป็น แต่ในกรณีนี้โค้ดจะซับซ้อนเกินไป สำหรับการหารใด ๆ คุณต้องเขียน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 จะไม่สนใจที่จะรวมข้อยกเว้นพิเศษสำหรับสุนัขที่มีอุปกรณ์ครบครันไว้ในภาษานี้ แต่เราได้แก้ไขการกำกับดูแลของพวกเขาแล้ว :)
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION