Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Java

ข้อยกเว้น Java และวิธีจัดการกับมัน

ในฐานะนักพัฒนา Java คุณควรมีความรู้ที่ดีเกี่ยวกับข้อยกเว้น Java และการจัดการข้อยกเว้น

บทช่วยสอนนี้ให้ความรู้พื้นฐานที่โปรแกรมเมอร์ทุกคนต้องมีเมื่อทำงานกับโปรแกรม Java ในการเริ่มต้น มาเริ่มด้วยการทำความเข้าใจว่า Java Exceptions คืออะไร

ข้อยกเว้นของ Java คืออะไร

โปรแกรม Java อาจประสบปัญหาที่ส่งผลให้โปรแกรมถูกยกเลิกกะทันหันระหว่างการดำเนินการ ปัญหาเหล่านี้เรียกว่าข้อยกเว้น

โปรแกรมเมอร์ที่ดีควรสามารถรับรู้ข้อผิดพลาดที่อาจเกิดขึ้นระหว่างการดำเนินการและจัดเตรียมเส้นทางสำรองสำหรับโปรแกรมเพื่อใช้ในกรณีที่เกิดข้อยกเว้นดังกล่าว การปฏิบัตินี้เรียกว่าการจัดการข้อยกเว้น

ตอนนี้คุณอาจสงสัยว่าทำไมเราถึงต้องการการจัดการข้อยกเว้นเลย ทำไมไม่เขียนโปรแกรมที่ไม่มีข้อยกเว้น

เหตุใดเราจึงต้องมีการจัดการข้อยกเว้น

ปรากฏว่าการเขียนโปรแกรมที่ไม่ทำให้เกิดข้อยกเว้นนั้นไม่ง่ายอย่างที่คิด โดยส่วนใหญ่ ข้อผิดพลาดที่หลีกเลี่ยงไม่ได้เหล่านี้อยู่เหนือการควบคุมของโปรแกรมเมอร์

โปรแกรมที่ยอมรับการป้อนข้อมูลของผู้ใช้มีแนวโน้มที่จะทำงานเป็นข้อยกเว้น เนื่องจากการป้อนข้อมูลที่ไม่ถูกต้องที่ผู้ใช้จัดเตรียม การอ่านไฟล์ภายนอกก็เช่นกัน โดยพิจารณาถึงโอกาสที่ไฟล์เหล่านั้นจะถูกย้าย เปลี่ยนชื่อ หรือลบโดยแหล่งภายนอกโดยที่โปรแกรมเมอร์ไม่ทราบ

ในกรณีเช่นนี้ โปรแกรมจะต้องสามารถจัดการกับข้อยกเว้นได้อย่างสวยงามโดยไม่ต้องยุติการดำเนินการ

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

ข้อยกเว้นทั้งหมดใน Java ควรเป็นลูกของ Exception คลาสซึ่งเป็นลูกของ Throwable ชั้นเรียน

สองคลาสย่อยหลักของ Exception คลาสคือ RuntimeException และ IOException .

ข้อยกเว้นเทียบกับข้อผิดพลาด

คลาสลูกอื่นของ Throwable คลาสคือ Error ระดับ. อย่างไรก็ตาม ข้อผิดพลาดแตกต่างจากข้อยกเว้น

ข้อผิดพลาดระบุถึงปัญหาที่ JVM อาจพบระหว่างการดำเนินการ ปัญหาเหล่านี้มักจะร้ายแรงและไม่สามารถกู้คืนได้ หน่วยความจำรั่วและปัญหาความไม่เข้ากันของไลบรารีเป็นสาเหตุทั่วไปของข้อผิดพลาดในโปรแกรม

StackOverflowError และ OutOfMemoryError เป็นสองตัวอย่างของข้อผิดพลาด Java

ตรวจสอบแล้วและไม่ได้ตรวจสอบข้อยกเว้น

เราสามารถแบ่ง Java Exceptions ออกเป็นสองประเภทหลัก:ตรวจสอบแล้ว และ ไม่ถูกเลือก ข้อยกเว้น

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

ข้อยกเว้นที่ไม่ได้ตรวจสอบคือข้อยกเว้นที่คอมไพเลอร์ละเว้นเมื่อทำการคอมไพล์โปรแกรม ไม่ว่าเราจะจัดการกับข้อยกเว้นเหล่านี้ในโปรแกรมหรือไม่ก็ตาม ไม่สำคัญว่าโปรแกรมจะถูกคอมไพล์เมื่อใด เนื่องจากข้อยกเว้นเหล่านี้ไม่ได้กำหนดการจัดการข้อยกเว้น โปรแกรมของเราจึงสามารถเรียกใช้ RuntimeExceptions ที่ส่งผลให้โปรแกรมถูกยกเลิก

คลาสทั้งหมดที่ขยาย RuntimeException คลาสเป็นข้อยกเว้นที่ไม่ได้ตรวจสอบ สองตัวอย่างของคลาสดังกล่าวคือ NullPointerException และ ArrayIndexOutOfBoundsException .

เมธอดที่ใช้ทั่วไปในคลาสข้อยกเว้น

เราจะพูดถึงวิธีการที่ใช้กันทั่วไปใน Java Exception คลาส:

  1. getMessage :ส่งคืนข้อความที่มีรายละเอียดเกี่ยวกับข้อยกเว้นที่เกิดขึ้น
  2. printStackTrace :ส่งคืน stack trace ของข้อยกเว้นที่เกิดขึ้น
  3. toString :ส่งคืนชื่อคลาสและข้อความที่ส่งคืนด้วย getMessage วิธีการ

วิธีจัดการกับข้อยกเว้น

มาดูกันว่าเราจัดการกับข้อยกเว้นใน Java ได้อย่างไร:

ลองจับ

เราสามารถตรวจจับข้อยกเว้นและจัดการได้อย่างถูกต้องโดยใช้ ลองจับ บล็อกใน Java

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

ไวยากรณ์พื้นฐานของบล็อก try-catch มีดังนี้:

try {
    //exception-prone code
}
catch(Exception e) {
    //error handling logic
}

ด้วยวิธีนี้ โปรแกรมจะไม่หยุดการทำงานเมื่อโปรแกรมส่งข้อยกเว้น แต่จะได้รับการจัดการอย่างงดงามแทน

มาดูวิธีจัดการกับ IOExceptions ถูกส่งโดย FileReader คลาสในโปรแกรม Java

ตัวอย่าง:

import java.io.FileReader;

public class TryCatchBlockExample {

    public static void main(String[] args) {

        try {
            FileReader file = new FileReader("source.txt");
            file.read();
        }
        catch(Exception e) {
            e.printStackTrace();
        }
    }
}

ที่นี่ เราได้ใช้บล็อก catch เดียวเพื่อจัดการกับ FileNotFoundException โยนเมื่อสร้างอินสแตนซ์ FileReader คลาสและ IOException โยนโดย read() วิธีการของ FileReader ชั้นเรียน

ข้อยกเว้นทั้งสองนี้เป็นลูกของ Exception ชั้นเรียน

นอกจากนี้เรายังสามารถใช้คำสั่ง catch หลายตัวเพื่อตรวจจับข้อผิดพลาดประเภทต่างๆ ที่เกิดจากโค้ดภายในคำสั่ง try ครั้งเดียว สำหรับตัวอย่างก่อนหน้านี้ เราสามารถใช้บล็อก catch เพื่อดักจับ FileNotFoundException และบล็อก catch อื่นสำหรับ IOException ตามที่แสดงข้อมูลโค้ดต่อไปนี้:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class TryCatchBlockExample {

    public static void main(String[] args) {

        try {
            FileReader file = new FileReader("source.txt");
            file.read();
            file.close();
        }
        catch(FileNotFoundException e) {
            e.printStackTrace();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
    }
}

หากข้อยกเว้นส่งตรงกับข้อยกเว้นที่จัดการโดยคำสั่ง catch แรก จะถูกจัดการโดยตรรกะภายในคำสั่ง catch แรก

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

ตั้งแต่ FileNotFoundException เป็นประเภทย่อยของ IOException โดยใช้คำสั่ง catch ที่ 2 เพื่อดักจับ FileNotFoundException จะไม่ทำงาน มันจะถูกจัดการโดยคำสั่ง catch แรกและจะไม่ไปถึงคำสั่งที่ 2

หมายเหตุ:จำเป็นต้องใช้คำสั่ง catch อย่างน้อยหนึ่งคำสั่งพร้อมกับคำสั่ง try

สุดท้าย

เมื่อเราใช้ ลองจับ บล็อกเพื่อดักจับข้อยกเว้นในโปรแกรมของเรา มีบางกรณีที่เราต้องการใช้ตรรกะบางอย่างแม้ว่าจะตรวจพบข้อยกเว้นหรือไม่ก็ตาม ในกรณีเช่นนี้ เราสามารถใช้ try-catch-finly บล็อกแทนที่จะเป็นแค่ ลองจับ บล็อก

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

ตัวอย่างเช่น เมื่อเราใช้ FileReader คลาสในการอ่านไฟล์ จำเป็นต้องปิดไฟล์ที่เปิดอยู่เมื่อสิ้นสุดการประมวลผลไม่ว่าจะมีข้อยกเว้นเกิดขึ้นหรือไม่ก็ตาม เพื่อให้แน่ใจว่าสิ่งนี้ เราสามารถวางรหัสเพื่อปิดไฟล์ใน finally คำชี้แจง

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class TryCatchFinallyBlockExample {

    public static void main(String[] args) {
        FileReader file = null;
        try {
            file = new FileReader("source.txt");
            file.read();
        }
        catch(FileNotFoundException e) {
            e.printStackTrace();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
        finally {
            file.close();
        }
    }
}

อย่างไรก็ตาม หากคุณพยายามคอมไพล์โค้ดข้างต้น โค้ดจะไม่ถูกคอมไพล์เนื่องจาก IOException ที่ไม่สามารถจัดการได้ . นี่เป็นเพราะว่า close() วิธีการของ FileReader คลาสยังสามารถโยน IOExceptions . ดังนั้น เราต้องวางส่วนนี้ไว้ในบล็อกลองอีกอันดังนี้:

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class TryCatchFinallyBlockExample {

    public static void main(String[] args) {
        FileReader file = null;

        try {
            file = new FileReader("source.txt");
            file.read();
        }
        catch(FileNotFoundException e) {
            e.printStackTrace();
        }
        catch(IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                file.close();
            }
            catch(IOException e) {
                e.printStackTrace();
            }
        }
    }
}

ขว้าง

การจัดการข้อผิดพลาดโดยใช้ throws คำหลักใน Java นั้นง่าย ที่จริงแล้ว ในแนวทางนี้ คุณไม่ได้จัดการกับข้อยกเว้นที่เกิดขึ้นจริง ๆ แต่เราโยนข้อยกเว้นออกจากเมธอดปัจจุบันไปยังเมธอดที่เรียกว่าเมธอดปัจจุบันแทน จากนั้นการมอบข้อผิดพลาดจะกลายเป็นความรับผิดชอบของวิธีการภายนอก

ในการโยนข้อยกเว้นออกจากเมธอด คุณเพียงแค่ประกาศว่าเมธอดนี้อาจส่งข้อยกเว้นที่พิจารณาแล้ว มาดูกันว่าเราจะจัดการกับ IOExceptions . ได้อย่างไร ถูกส่งโดย FileReader ชั้นเรียนโดยใช้วิธีนี้

ตัวอย่าง:

import java.io.FileReader;
import java.io.IOException;

public class ThrowsExample {

    public void readFile throws IOException {
        FileReader file = new FileReader("source.txt");
        file.read();
        file.close();
    }
}

ขว้าง

ไม่เหมือนกับวิธีอื่นๆ ในรายการนี้ throw คีย์เวิร์ดไม่ได้ใช้ในการจัดการข้อผิดพลาด แต่เนื่องจากคนส่วนใหญ่สับสน throw คีย์เวิร์ดที่มี throw เราคิดว่าควรพูดคุยกันที่นี่จะดีกว่า

throw คีย์เวิร์ดใช้เพื่อเรียกใช้ข้อยกเว้นอย่างชัดเจน เราสามารถโยนข้อยกเว้นที่สร้างอินสแตนซ์ใหม่หรือข้อยกเว้นที่ติดอยู่ในเมธอดได้

public class ThrowExample {

    public void invalidate(int amount) throws Exception {
        if (amount < 500) {
            throw new Exception("Amount not sufficient");
        }
    }
}

ข้อยกเว้นที่กำหนดโดยผู้ใช้

นอกจากการใช้ข้อยกเว้น Java ในตัวแล้ว คุณยังสามารถกำหนดข้อยกเว้นของคุณเองได้ คุณสามารถกำหนดเป็นข้อยกเว้นที่เลือกหรือไม่เลือกก็ได้ ในการสร้างข้อยกเว้นที่ตรวจสอบใหม่ ข้อยกเว้นใหม่ของคุณควรขยาย Exception ชั้นเรียน

เพื่อสร้าง ไม่ถูกตรวจสอบ ข้อยกเว้น ขยาย RuntimeException ชั้นเรียน

ในตัวอย่างโค้ดต่อไปนี้ เราได้สร้างข้อยกเว้นการตรวจสอบที่ผู้ใช้กำหนด:

public class InvalidLengthException extends Exception {
    private int length;
    private String message;

    public InvalidLengthException(int length, String message) {
        this.length=length;
        this.message=message;
    }

    public int getAmount() {
        return this.length;
    }

    public String getMessage() {
        return this.message;
    }
}

ตอนนี้เราสามารถใช้ข้อยกเว้นข้างต้นในตรรกะของโปรแกรมดังนี้:

public class InputChecker {

    private int minLength;
    private int maxLength;

    public InputChecker(int minLength, int maxLength) {
        this.minLength=minLength;
        this.maxLength=maxLength;
    }

    public void checkStringLength(String strInput) throws InvalidLengthException {
        int strLength = strInput.length();
        if (strLength < minLength) {
            throw new InvalidLengthException(strLength, "Input should have minimum "+minLength+" characters");
        }
        else if (strLength > maxLength){
            throw new InvalidLengthException(strLength, "Input should have maximum "+maxLength+" character");
        }
    }
}

หากเราตรวจสอบความยาวของสตริงโดยใช้ InputChecker คลาส มันจะโยน InvalidLengthException หากความยาวของสตริงต่ำกว่าความยาวขั้นต่ำหรือสูงกว่าความยาวสูงสุด

public class Main {

    public static void main(String[] args) {
        InputChecker ic = new InputChecker(2, 7);
        try {
            ic.checkStringLength("longer than the maximum length");
        }
        catch(InvalidLengthException e) {
            e.printStackTrace();
        }
    }
}

เมื่อเราเรียกใช้ข้อมูลโค้ดข้างต้น โค้ดดังกล่าวจะส่ง InvalidLengthException และเราจะได้ผลลัพธ์ดังต่อไปนี้:

InvalidLengthException: Input should have maximum 7 character
    at InputChecker.checkStringLength(InputChecker.java:17)
    at Main.main(Main.java:6)

บทสรุป

ในบทช่วยสอนนี้ เราได้ให้ข้อมูลเบื้องต้นเกี่ยวกับ Java Exceptions ที่กระชับและรวดเร็วแก่คุณ เราหวังว่าคุณจะเข้าใจดีว่าข้อยกเว้นคืออะไรและจะจัดการอย่างไรในโปรแกรม Java ของคุณ