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

กฎการจัดการ Exception ใน Method Overriding ใน Java

เมื่อ override method ที่โยน checked exception ต้องปฏิบัติตามกฎของ Java compiler

กฎที่ 1: ต้องโยน Exception เดียวกัน หรือ Subclass (Covariant)

Subclass method สามารถโยน exception เดียวกับ superclass หรือ subclass ของ exception นั้น (specific มากกว่า)

ตัวอย่าง: โยน Subclass Exception (ถูกต้อง)


import java.io.*;

abstract class Super {
    public void readFile(String path) throws IOException { ... }
}

public class Sub extends Super {
    @Override
    public void readFile(String path) throws FileNotFoundException { // IOException subclass
        // FileNotFoundException extends IOException
    }
}

ตัวอย่าง: โยน Exception เดียวกัน (ถูกต้อง)


abstract class Super {
    public void method() throws FileNotFoundException { ... }
}

public class Sub extends Super {
    @Override
    public void method() throws FileNotFoundException { ... } // same exception
}

กฎที่ 2: ห้ามโยน Superclass Exception (Contravariant - ไม่ได้)

Subclass ไม่สามารถ โยน exception ที่เป็น superclass ของ exception ใน superclass method

ตัวอย่าง: ผิด (Compile Error)


abstract class Super {
    public void method() throws FileNotFoundException { ... }
}

public class Sub extends Super {
    @Override
    public void method() throws IOException { } // Compile Error!
    // IOException เป็น superclass ของ FileNotFoundException
}

Compile Error


error: method() in Sub cannot override method() in Super
  overridden method does not throw IOException

กฎที่ 3: สามารถไม่โยน Exception เลยได้

Subclass method สามารถ ไม่โยน exception ใดๆ ได้ (แม้ superclass จะโยน)

ตัวอย่าง: ไม่โยน Exception (ถูกต้อง)


abstract class Super {
    public void method() throws FileNotFoundException { ... }
}

public class Sub extends Super {
    @Override
    public void method() { // ไม่ throws อะไรเลย
        System.out.println("Handled internally");
    }
}

กฎที่ 4: Unchecked Exception (RuntimeException) - ไม่มีข้อจำกัด

RuntimeException และ subclass ไม่ถูกบังคับโดย compiler สามารถ override และโยนได้อิสระ

ตัวอย่าง


class Super {
    public void method() { throw new RuntimeException(); }
}

class Sub extends Super {
    @Override
    public void method() { throw new NullPointerException(); } // OK
    // หรือไม่โยนเลยก็ได้
}

สรุปตาราง

Superclass throwsSubclass throwsValid?
IOExceptionIOException✓
IOExceptionFileNotFoundException✓ (subclass)
IOExceptionException✗ (superclass)
IOException(none)✓
FileNotFoundExceptionIOException✗ (superclass)
RuntimeExceptionAny RuntimeException✓ (unchecked)

เหตุผลทาง Design (Liskov Substitution Principle)

Client code ที่เรียก superclass method คาดหวังว่าจะจัดการ exception ที่ระบุไว้ หาก subclass โยน exception กว้างกว่า (superclass) client อาจไม่ catch ได้ → แตก LSP

Best Practice

  • Override method ควรโยน exception specific มากที่สุดที่เป็นไปได้
  • หาจับ exception ไว้ใน subclass ให้ wrap เป็น custom exception ที่ specific
  • หลีกเลี่ยง throws Exception / throws Throwable ใน API public