1. ข้อยกเว้น

>

ท้ายที่สุดแล้ว โปรแกรมเมอร์คิดที่จะสร้างมาตรฐานและทำให้การจัดการข้อผิดพลาดเป็นไปโดยอัตโนมัติ สิ่งนี้เกิดขึ้นเมื่อมีการคิดค้นข้อยกเว้น ขณะนี้กลไกข้อยกเว้นจัดการ 80% ของสถานการณ์พิเศษ

หากนักวิชาการบางคนมีข้อยกเว้น ก็น่าจะเป็นเรื่องของวิทยานิพนธ์ระดับปริญญาเอกของเขาหรือเธอ หากโปรแกรมเมอร์คิดขึ้นมา เขาอาจได้รับการตบหลังอย่างเป็นมิตรจากเพื่อนร่วมงาน: "ไม่เป็นไร พี่ชาย"

เมื่อเกิดข้อผิดพลาดในโปรแกรม Java เช่น การหารด้วย0สิ่งมหัศจรรย์บางอย่างจะเกิดขึ้น:

ขั้นตอนแรก

มีการสร้างวัตถุข้อยกเว้นพิเศษซึ่งมีข้อมูลเกี่ยวกับข้อผิดพลาดที่เกิดขึ้น

ทุกอย่างใน Java เป็นออบเจกต์ และข้อยกเว้นก็ไม่มีข้อยกเว้น 🙂 ออบเจ็กต์ข้อยกเว้นมีคลาสของตัวเอง และสิ่งเดียวที่ทำให้มันแตกต่างจากคลาสทั่วไปก็คือพวกมันสืบทอดคลาสThrowableมา

ขั้นตอนที่สอง

วัตถุยกเว้นคือ "โยน" บางทีถ้อยคำที่นี่อาจจะดีกว่า "การส่งข้อยกเว้น" เป็นเหมือนการเรียกใช้สัญญาณเตือนไฟไหม้หรือส่งเสียงเตือน "DEFCON 1"

เมื่อข้อยกเว้นถูกส่งไปยังเครื่อง Java การทำงานปกติของโปรแกรมจะหยุดลงและ "โปรโตคอลฉุกเฉิน" จะเริ่มต้นขึ้น

ขั้นตอนที่สาม

วิธีการที่ข้อยกเว้นถูกส่งออกไปทันที ข้อยกเว้นจะถูกส่งผ่านไปยังวิธีการโทร ซึ่งจะออกทันทีเช่นกัน และต่อไปเรื่อยๆ จนกว่าจะmainหมดเมธอด เมื่อmainเมธอดสิ้นสุดลง โปรแกรมก็เช่นกัน

ตัวอย่าง:

รหัส เอาต์พุตคอนโซล
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Your attention, please! Preparing for the end of the world");
      endTheWorld();
      System.out.println("The world ended successfully");
   }

   public static void endTheWorld()
   {
      System.out.println("We're doing something important");
      doSomeWork(0);
      System.out.println("Everything is working well");
   }

   public static void doSomeWork(int n)
   {
      System.out.println("Nothing terrible will happen: " + n);
      System.out.println(2 / n);
      System.out.println("Nothing terrible happened: " + n);
   }
}
Your attention, please! Preparing for the end of the world
We're doing something important
Nothing terrible will happen: 0

ข้อยกเว้นเกิดขึ้นในบรรทัดที่ 20: หารด้วย 0เครื่อง Java จะสร้างข้อยกเว้นขึ้น มาทันที — ArithmeticExceptionวัตถุและ "ส่ง" ไปยังเมธอด

เมธอดdivide()จะสิ้นสุดลงทันที ดังนั้นเราจึงไม่เห็นสตริง: ไม่มีอะไรเลวร้ายเกิดขึ้น: 0 โปรแกรมกลับไปที่เมธอดendTheWorld()และสถานการณ์ซ้ำ: มีข้อยกเว้นที่ไม่สามารถจัดการได้ในระบบ ซึ่งหมายความว่าเมธอดendTheWorld()จะยุติลงอย่างผิดปกติเช่นกัน จากนั้นmainเมธอดจะสิ้นสุดลง และโปรแกรมจะหยุดทำงาน

จุดประสงค์ของข้อยกเว้นเหล่านี้คืออะไร? คุณสามารถเขียนโค้ดของคุณเองเพื่อตรวจจับข้อยกเว้นบางประเภทและเขียนตรรกะของคุณเองเพื่อจัดการกับสถานการณ์พิเศษ


2. จับข้อยกเว้น:try-catch

Java มีกลไกการจับข้อยกเว้นที่ให้คุณหยุดการยุติเมธอดที่ผิดปกตินี้ ดูเหมือนว่า:

try
{
   // Code where an exception might occur
}
catch(ExceptionType name)
{
   // Exception handling code
}

โครงสร้างนี้เรียกว่าtry-catchบล็อก

รหัสที่อาจมีข้อยกเว้นเกิดขึ้นจะถูกห่อด้วยวงเล็บปีกกา นำหน้าด้วยคำtryว่า

หลังจากวงเล็บปีกกา เรามี คำ สำคัญcatchและในวงเล็บคือการประกาศตัวแปรข้อยกเว้น ตามด้วย วงเล็บปีกกาที่ ตัดโค้ดที่จะดำเนินการหากเกิดข้อยกเว้นของประเภทที่ระบุ

หากไม่มีข้อยกเว้นเกิดขึ้นระหว่างการดำเนินการของ " รหัสหลัก " ดังนั้นรหัสภายในบล็อก catch จะไม่ถูกดำเนินการ หากมีข้อยกเว้นเกิดขึ้น มันจะเป็น (หากประเภทของข้อยกเว้นที่เกิดซ้ำเหมือนกับประเภทของตัวแปรในวงเล็บ)

ตัวอย่าง:

รหัส เอาต์พุตคอนโซล
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Hadron Collider launched");

      try
      {
         launchHadronCollider(1);
         launchHadronCollider(0);
      }
      catch(Exception e)
      {
         System.out.println("Error! Caught an exception");
         System.out.println("The planet was sucked into a black hole!");
      }

      System.out.println("The Hadron Collider stopped");
   }

   public static void launchHadronCollider(int n)
   {
      System.out.println("Everything is working well: " + n);
      System.out.println(2/n);
      System.out.println("There are no problems: " + n);
   }
}
Hadron Collider launched
Everything is working fine: 1
2
There are no problems: 1
Everything is working fine: 0
Error! Caught an exception
The planet has been sucked into a black hole!
The Hadron Collider is stopped


3. หลายcatchบล็อก

บล็อกจับหลายอัน

ตามทฤษฎีแล้ว ข้อยกเว้นทุกประเภทสามารถโยนลงในบล็อกของโค้ดได้ บางอย่างคุณจะต้องการจัดการแบบหนึ่ง บางอย่างอีกวิธีหนึ่ง และบางอย่างที่คุณจะตัดสินใจไม่จัดการเลย

นักพัฒนา Java ตัดสินใจที่จะช่วยคุณและให้คุณเขียนบล็อกเดียวไม่ได้ แต่หลายcatchบล็อกหลังจากtryบล็อก

try
{
   // Code where an exception might occur
}
catch (ExceptionType1 name1)
{
   // Code for handling ExceptionType1
}
catch (ExceptionType2 name2)
{
   // Code for handling ExceptionType2
}
   catch (ExceptionType3 name3)
{
   // Code for handling ExceptionType3
}

ตัวอย่าง:

รหัส เอาต์พุตคอนโซล
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Start of main method");
      try
      {
         calculate(0);
      }
      catch (ArithmeticException e)
      {
         System.out.println("Division by 0");
      }
      catch(Exception e)
      {
         System.out.println("Caught some kind of exception");
      }

      System.out.println("End of main method");
   }

   public static void calculate(int n)
   {
      System.out.println("Start of calculate method: " + n);
      System.out.println(2/n);
      System.out.println("End of calculate method: " + n);
   }
}
Start of main method
Start of calculate method: 0
Division by 0
End of main method


4. ลำดับของcatchบล็อก

ข้อยกเว้นที่เกิดขึ้นในtryบล็อกสามารถจับได้โดยcatchบล็อก เดียวเท่านั้น คุณไม่สามารถมีสถานการณ์การจัดการข้อยกเว้นที่รหัสจากหลายcatchบล็อกถูกดำเนินการ

แต่ลำดับของบล็อกมีความสำคัญ

คุณอาจมีสถานการณ์ที่หลายบล็อกอาจจับข้อยกเว้นได้ หากเป็นกรณีนี้ ข้อยกเว้นจะถูกดักจับโดย บล็อก catch อันใดก็ตาม ที่มาก่อน (ใกล้กับtryบล็อกมากที่สุด)

คุณจะมีสถานการณ์ที่ catch block หลายอันสามารถจับข้อยกเว้นเดียวกันได้อย่างไร

ข้อยกเว้นทั้งหมดอยู่ในลำดับชั้นการสืบทอดเดียว — ดูไดอะแกรม

ลำดับชั้นข้อยกเว้น

อ็อบเจ็กต์ArithmeticExceptionสามารถถูกกำหนดให้กับตัวแปรที่มีประเภทArithmeticExceptionหรือคลาสบรรพบุรุษใดๆ ของมัน: RuntimeExceptionและExceptionThrowableดูไดอะแกรม

เราจะพูดถึงการสืบทอดและคลาสบรรพบุรุษในระดับ 21 มากขึ้น

รหัสนี้จะรวบรวมได้ดี:

ประโยชน์ของมรดก:
ArithmeticException ae    = new ArithmeticException();
RuntimeException runtime  = new ArithmeticException();
Exception exception       = new ArithmeticException();
Throwable trwbl           = new ArithmeticException();

ดังนั้นคุณสามารถจับบล็อกArithmeticExceptionใด ๆ จาก 4 catchบล็อกด้านบน

ตัวอย่างที่ 1:

รหัส เอาต์พุตคอนโซล
class Solution
{
   public static void main(String[] args)
   {
      System.out.println("Start of main method");
      try
      {
         calculate(0);
      }
      catch(ArithmeticException e)
      {
         System.out.println("Division by 0");
      }
      catch(Exception e)
      {
         System.out.println("Caught some kind of exception");
      }

      System.out.println("End of main method");
   }

   public static void calculate(int n)
   {
      System.out.println("Start of calculate method: " + n);
      System.out.println(2/n);
      System.out.println("End of calculate method: " + n);
   }
}
Start of main method
Start of calculate method: 0
Division by 0
End of main method

ในตัวอย่างนี้ArithmeticExceptionทั้งบล็อกcatch (Exception e)และcatch (ArithmeticException e)บล็อก สามารถจับได้ มันจะถูกบล็อกที่อยู่ใกล้กับ บล็อกมากที่สุด - บล็อกtryแรกcatch

เพื่อหลีกเลี่ยงความประหลาดใจ วิธีที่ดีที่สุดคือวางcatchบล็อกที่สามารถตรวจจับข้อยกเว้นได้เกือบทั้งหมดใกล้กับจุดสิ้นสุดของรายการcatchบล็อก

ประเภทThrowableโดยทั่วไปสามารถจับทุกข้อยกเว้นที่เป็นไปได้ใน Java หากคุณวางไว้ในcatchบล็อคแรก โค้ดจะไม่คอมไพล์ เนื่องจากคอมไพเลอร์รู้ว่ามีบล็อคโค้ดที่ไม่สามารถเข้าถึงได้