เหตุใดวิธีการลบล้างจึงไม่สามารถทำให้ข้อยกเว้นกว้างกว่าวิธีการลบล้างได้


108

ฉันกำลังอ่านหนังสือ SCJP 6 โดย Kathe sierra และได้พบกับคำอธิบายเกี่ยวกับการโยนข้อยกเว้นในวิธีการที่ถูกลบล้าง ฉันค่อนข้างไม่เข้าใจ มีใครอธิบายให้ฉันฟังได้ไหม

วิธีการลบล้างจะต้องไม่ทิ้งข้อยกเว้นที่ตรวจสอบแล้วซึ่งใหม่หรือกว้างกว่าที่ประกาศโดยวิธีการแทนที่ ตัวอย่างเช่นวิธีการที่ประกาศ FileNotFoundException ไม่สามารถถูกแทนที่โดยวิธีการที่ประกาศ SQLException ข้อยกเว้นหรือข้อยกเว้นอื่น ๆ ที่ไม่ใช่รันไทม์เว้นแต่จะเป็นคลาสย่อยของ FileNotFoundException


1
นี่คือเว็บไซต์ที่คุณอาจพบว่ามีประโยชน์: javapractices.com/topic/TopicAction.do?Id=129
Tim Bish

คำตอบ:


161

หมายความว่าหากเมธอดประกาศว่าจะทิ้งข้อยกเว้นที่กำหนดไว้เมธอดการลบล้างในคลาสย่อยจะสามารถประกาศให้โยนข้อยกเว้นนั้นหรือคลาสย่อยเท่านั้น ตัวอย่างเช่น:

class A {
   public void foo() throws IOException {..}
}

class B extends A {
   @Override
   public void foo() throws SocketException {..} // allowed

   @Override
   public void foo() throws SQLException {..} // NOT allowed
}

SocketException extends IOExceptionแต่SQLExceptionไม่

นี่เป็นเพราะความหลากหลาย:

A a = new B();
try {
    a.foo();
} catch (IOException ex) {
    // forced to catch this by the compiler
}

ถ้าBได้ตัดสินใจที่จะโยนSQLExceptionแล้วคอมไพเลอร์ไม่สามารถบังคับให้คุณจับมันเพราะคุณจะหมายถึงตัวอย่างของBโดย superclass ของ A- ในทางกลับกันคลาสย่อยใด ๆ ของIOExceptionจะถูกจัดการโดยอนุประโยค (จับหรือโยน) ที่จับIOException

กฎที่คุณต้องสามารถอ้างถึงออบเจ็กต์โดยใช้ superclass คือLiskov Substitution Principle

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


นอกจากนี้ยังใช้ในขณะที่ใช้อินเทอร์เฟซ? ฉันไม่แน่ใจว่าการใช้งานอินเทอร์เฟซยังคงเรียกว่า "การลบล้าง" อยู่หรือไม่
Muhammad Gelbana

วิธีการเกี่ยวกับ @Override public void foo () {.. } ฉันรู้ว่าอนุญาต แต่คำอธิบายไม่ชัดเจนสำหรับกรณีนี้
nascar

4
@danip วิธีการแทนที่สามารถโยนส่วนย่อยของข้อยกเว้นใด ๆ ที่โยนมาจากเมธอด overriden ชุดว่างเป็นส่วนย่อยด้วย นั่นคือเหตุผลที่@Override public void foo() {...}ถูกกฎหมาย
พัฒนา Marius Žilėnas

@Bozho ไม่ควรเป็นเช่นนั้นหากวิธีการประกาศว่าจะทิ้งข้อยกเว้นที่กำหนดไว้วิธีการแทนที่ในคลาสย่อยสามารถประกาศได้ว่าจะโยนข้อยกเว้นนั้นหรือคลาสย่อยหรือประกาศ NO พ่นประโยคเลย
Raman Sahasi

แล้วการเอาชนะในโลกแห่งความเป็นจริงเป็นอย่างไร? ฉันต้องการลบล้างวิธีการจากอินเทอร์เฟซที่ใช้งาน แต่การใช้งานของฉันมีการชะลอตัวของการพ่นและอินเทอร์เฟซไม่ได้ ขั้นตอนมาตรฐานที่นี่คืออะไร?
AP

22

วิธีการลบล้างสามารถทำให้เกิดข้อยกเว้น (รันไทม์) ที่ไม่ได้ตรวจสอบได้โดยไม่คำนึงว่าเมธอดที่ถูกลบล้างจะประกาศข้อยกเว้นหรือไม่

ตัวอย่าง:

class Super {
    public void test() {
        System.out.println("Super.test()");
    }
}

class Sub extends Super {
    @Override
    public void test() throws IndexOutOfBoundsException {
        // Method can throw any Unchecked Exception
        System.out.println("Sub.test()");
    }
}

class Sub2 extends Sub {
    @Override
    public void test() throws ArrayIndexOutOfBoundsException {
        // Any Unchecked Exception
        System.out.println("Sub2.test()");
    }
}

class Sub3 extends Sub2 {
    @Override
    public void test() {
        // Any Unchecked Exception or no exception
        System.out.println("Sub3.test()");
    }
}

class Sub4 extends Sub2 {
    @Override
    public void test() throws AssertionError {
        // Unchecked Exception IS-A RuntimeException or IS-A Error
        System.out.println("Sub4.test()");
    }
}

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

14

ในความคิดของฉันมันเป็นความล้มเหลวในการออกแบบไวยากรณ์ Java ความหลากหลายไม่ควร จำกัด การใช้งานการจัดการข้อยกเว้น ในความเป็นจริงภาษาคอมพิวเตอร์อื่น ๆ ไม่ทำ (C #)

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


8

ฉันให้คำตอบนี้สำหรับคำถามเก่าที่นี่เนื่องจากไม่มีคำตอบใดที่บอกความจริงที่ว่าวิธีการลบล้างไม่สามารถทิ้งสิ่งที่วิธีการลบล้างสามารถโยนได้อีกต่อไป:

1) โยนข้อยกเว้นเดียวกัน

public static class A 
{
    public void m1()
       throws IOException
    {
        System.out.println("A m1");
    }

}

public static class B 
    extends A
{
    @Override
    public void m1()
        throws IOException
    {
        System.out.println("B m1");
    }
}

2) โยนคลาสย่อยของข้อยกเว้นการโยนของเมธอด overriden

public static class A 
{
    public void m2()
       throws Exception
    {
        System.out.println("A m2");
    }

}

public static class B 
    extends A
{
    @Override
    public void m2()
        throws IOException
    {
        System.out.println("B m2");
    }
}

3) โยนอะไรเลย

public static class A 
{   
    public void m3()
       throws IOException
    {
        System.out.println("A m3");
    }
}

public static class B 
    extends A
{   
    @Override
    public void m3()
        //throws NOTHING
    {
        System.out.println("B m3");
    }
}

4) ไม่จำเป็นต้องมี RuntimeExceptions ในการพ่น

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


6

เพื่อเป็นตัวอย่างให้พิจารณา:

public interface FileOperation {
  void perform(File file) throws FileNotFoundException;
}

public class OpenOnly implements FileOperation {
  void perform(File file) throws FileNotFoundException {
    FileReader r = new FileReader(file);
  }
}

สมมติว่าคุณเขียน:

public class OpenClose implements FileOperation {
  void perform(File file) throws FileNotFoundException {
    FileReader r = new FileReader(file);
    r.close();
  }
}

สิ่งนี้จะทำให้คุณมีข้อผิดพลาดในการคอมไพล์เนื่องจาก r.close () พ่น IOException ซึ่งกว้างกว่า FileNotFoundException

ในการแก้ไขปัญหานี้หากคุณเขียน:

public class OpenClose implements FileOperation {
  void perform(File file) throws IOException {
    FileReader r = new FileReader(file);
    r.close();
  }
}

คุณจะได้รับข้อผิดพลาดในการคอมไพล์ที่แตกต่างกันเนื่องจากคุณกำลังใช้การดำเนินการ perform (... ) แต่มีข้อยกเว้นที่ไม่รวมอยู่ในนิยามของวิธีการของอินเทอร์เฟซ

เหตุใดสิ่งนี้จึงสำคัญ ผู้บริโภคของอินเทอร์เฟซอาจมี:

FileOperation op = ...;
try {
  op.perform(file);
}
catch (FileNotFoundException x) {
  log(...);
}

หาก IOException ได้รับอนุญาตให้โยนรหัสของไคลเอ็นต์จะไม่ถูกต้อง

โปรดทราบว่าคุณสามารถหลีกเลี่ยงปัญหาประเภทนี้ได้หากคุณใช้ข้อยกเว้นที่ไม่เลือก (ฉันไม่ได้แนะนำให้คุณทำหรือไม่ทำนั่นเป็นประเด็นทางปรัชญา)


4

ให้เราทำคำถามสัมภาษณ์ มีวิธีการที่พ่น NullPointerException ใน superclass เราสามารถแทนที่ด้วยวิธีการที่พ่น RuntimeException ได้หรือไม่?

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

  1. ข้อยกเว้นที่ตรวจสอบแล้วจะต้องถูกจับหรือเผยแพร่อย่างชัดเจนตามที่อธิบายไว้ในการจัดการข้อยกเว้นการลองจับขั้นพื้นฐาน ข้อยกเว้นที่ไม่เลือกไม่มีข้อกำหนดนี้ พวกเขาไม่ต้องถูกจับหรือถูกประกาศว่าโยน

  2. ตรวจสอบข้อยกเว้นใน Java ขยายคลาส java.lang.Exception ข้อยกเว้นที่ไม่ได้เลือกจะขยาย java.lang.RuntimeException

คลาสสาธารณะ NullPointerException ขยาย RuntimeException

ข้อยกเว้นที่ไม่ได้เลือกจะขยาย java.lang.RuntimeException นี่คือเหตุผลที่ NullPointerException เป็นข้อยกเว้นที่ไม่ได้ทำเครื่องหมาย

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

    public class Parent {
       public void name()  throws NullPointerException {
           System.out.println(" this is parent");
       }
}

public class Child  extends Parent{
     public  void name() throws RuntimeException{
             System.out.println(" child ");
     }

     public static void main(String[] args) {
        Parent parent  = new Child();
        parent.name();// output => child
    }
}

โปรแกรมจะคอมไพล์สำเร็จ ตัวอย่างที่ 2:

    public class Parent {
       public void name()  throws RuntimeException {
           System.out.println(" this is parent");
       }
}

public class Child  extends Parent{
     public  void name() throws  NullPointerException {
             System.out.println(" child ");
     }

     public static void main(String[] args) {
        Parent parent  = new Child();
        parent.name();// output => child
    }
}

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

    public class Parent {
       public void name()  throws IOException {
           System.out.println(" this is parent");
       }
}
public class Child  extends Parent{
     public  void name() throws IOException{
             System.out.println(" child ");
     }

     public static void main(String[] args) {
        Parent parent  = new Child();

        try {
            parent.name();// output=> child
        }catch( Exception e) {
            System.out.println(e);
        }

    }
}

โปรแกรมจะคอมไพล์สำเร็จ ตัวอย่างที่ 4: เมื่อเมธอดคลาสลูกโยนข้อยกเว้นที่ตรวจสอบเส้นขอบเทียบกับเมธอดคลาสพื้นฐานเดียวกัน

import java.io.IOException;

public class Parent {
       public void name()  throws IOException {
           System.out.println(" this is parent");
       }
}
public class Child  extends Parent{
     public  void name() throws Exception{ // broader exception
             System.out.println(" child ");
     }

     public static void main(String[] args) {
        Parent parent  = new Child();

        try {
            parent.name();//output=> Compilation failure
        }catch( Exception e) {
            System.out.println(e);
        }

    }
}

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


คำตอบที่สมบูรณ์แบบ!
Gaurav

2

สมมติว่าคุณมีซุปเปอร์คลาส A ด้วยวิธี M1 throwin E1 และคลาส B ที่ได้มาจาก A โดยใช้วิธี M2 แทนที่ M1 M2 ไม่สามารถโยนสิ่งที่แตกต่างหรือน้อยกว่าพิเศษกว่า E1

เนื่องจากความหลากหลายไคลเอนต์ที่ใช้คลาส A ควรจะสามารถปฏิบัติกับ B ได้เหมือนกับ A Inharitance ===> Is-a (B is-a A) จะเกิดอะไรขึ้นถ้ารหัสนี้ที่เกี่ยวข้องกับคลาส A กำลังจัดการข้อยกเว้น E1 เนื่องจาก M1 ประกาศว่าจะส่งข้อยกเว้นที่ตรวจสอบแล้วนี้ แต่ข้อยกเว้นประเภทอื่นก็ถูกโยนทิ้งไป ถ้า M1 ขว้าง IOException M2 ก็สามารถโยน FileNotFoundException ได้ดีเพราะเป็น IOException ลูกค้าของ A สามารถจัดการสิ่งนี้ได้โดยไม่มีปัญหา หากข้อยกเว้นถูกโยนออกไปกว้างกว่าลูกค้าของ A จะไม่มีโอกาสรู้เรื่องนี้ดังนั้นจึงไม่มีโอกาสจับได้


Perhac :: เป็นจริงสำหรับทั้งข้อยกเว้นที่เลือกและไม่เลือก? หรือแตกต่างกันไป?
ylnsagar

@ylnsagar นี่เป็นข้อยกเว้นที่ตรวจสอบเท่านั้น ข้อยกเว้นที่ไม่ได้ตรวจสอบ (ชนิดย่อยของ RuntimeException) อาจเรียกอีกอย่างว่า 'ข้อผิดพลาดของโปรแกรมเมอร์' และตามกฎทั่วไปแล้วไม่ควรลองจับด้วยเหตุนี้จึงไม่จำเป็นต้องมีการประกาศในส่วนคำสั่งพ่น ข้อยกเว้นที่ไม่ได้ตรวจสอบสามารถเกิดขึ้นได้ตลอดเวลาจากรหัสใด ๆ การสนทนาข้างต้นเกี่ยวข้องกับข้อยกเว้นที่ตรวจสอบแล้วเท่านั้น
Peter Perháč

@Perhac :: ใช่คุณพูดถูก แต่จากความเข้าใจของฉันโดยการอ่านบทความ นอกจากนี้ยังเป็นจริงสำหรับข้อยกเว้นที่ไม่ได้ตรวจสอบ ตัวอย่างเช่นถ้าเมธอดระดับซูเปอร์คลาสกำลังโยน Null Pointer Exception และถ้าคลาสย่อยแทนที่เมธอดจะแสดงข้อยกเว้น ที่นี่ Exception คือคลาส super ของ Null Pointer Exception จากนั้นคอมไพเลอร์จะไม่อนุญาตสิ่งนี้
ylnsagar

1

java.lang.Exception ขยาย java.lang.Throwable java.io.FileNotFoundException ขยาย java.lang.Exception ดังนั้นหากเมธอดพ่น java.io.FileNotFoundException จากนั้นในเมธอดการแทนที่คุณจะไม่สามารถเพิ่มลำดับชั้นที่สูงกว่า FileNotFoundException ได้เช่นคุณไม่สามารถโยน java.lang.Exception ได้ คุณสามารถโยนคลาสย่อยของ FileNotFoundException ได้ อย่างไรก็ตามคุณจะถูกบังคับให้จัดการ FileNotFoundException ในเมธอด overriden เคาะรหัสแล้วลองดู!

กฎอยู่ที่นั่นเพื่อให้คุณไม่สูญเสียการประกาศการขว้างแบบดั้งเดิมโดยการขยายความจำเพาะเนื่องจากความหลากหลายหมายความว่าคุณสามารถเรียกใช้เมธอด overriden ใน superclass ได้


1

วิธีการลบล้างจะต้องไม่ทิ้งข้อยกเว้นที่ตรวจสอบแล้วซึ่งใหม่หรือกว้างกว่าที่ประกาศโดยวิธีการแทนที่

ตัวอย่าง:

class Super {
    public void throwCheckedExceptionMethod() throws IOException {
        FileReader r = new FileReader(new File("aFile.txt"));
        r.close();
    }
}

class Sub extends Super {    
    @Override
    public void throwCheckedExceptionMethod() throws FileNotFoundException {
        // FileNotFoundException extends IOException
        FileReader r = new FileReader(new File("afile.txt"));
        try {
            // close() method throws IOException (that is unhandled)
            r.close();
        } catch (IOException e) {
        }
    }
}

class Sub2 extends Sub {
    @Override
    public void throwCheckedExceptionMethod() {
        // Overriding method can throw no exception
    }
}

1

วิธีการลบล้างจะต้องไม่ทิ้งข้อยกเว้นที่ตรวจสอบแล้วซึ่งใหม่หรือกว้างกว่าที่ประกาศโดยวิธีการแทนที่

นี่หมายถึงเมื่อคุณแทนที่เมธอดที่มีอยู่ข้อยกเว้นที่เมธอดที่โอเวอร์โหลดนี้ควรเป็นข้อยกเว้นเดียวกับที่เมธอดเดิมพ่นหรือคลาสย่อยใด ๆsubclasses

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


ตัวอย่าง

สมมติว่าเรามีระดับและประเภทรองของA มีเมธอดและคลาสได้ลบล้างเมธอดนี้ (ขอเรียกว่าเพื่อหลีกเลี่ยงความสับสน .. ) ทีนี้สมมติว่าพ่นและพ่นซึ่งเป็นซูเปอร์คลาส ตอนนี้เราเขียนโค้ดต่อไปนี้:BAm1Bm2m1E1m2E2E1

A myAObj = new B();
myAObj.m1();

โปรดทราบว่าm1คืออะไร แต่โทรไปm2(อีกครั้งวิธีลายเซ็นเหมือนกันในวิธีการมากเกินไปจึงไม่ได้รับสับสนกับm1และm2.. พวกเขาเป็นเพียงความแตกต่างในตัวอย่างนี้ ... พวกเขาทั้งสองมีลายเซ็นเดียวกัน) แต่ในเวลาคอมไพล์คอมไพเลอร์ java ทั้งหมดจะไปที่ประเภทการอ้างอิง (คลาสAในกรณีนี้) จะตรวจสอบเมธอดว่ามีอยู่หรือไม่และคาดว่าโปรแกรมเมอร์จะจัดการกับมัน E1ดังนั้นเห็นได้ชัดว่าคุณจะโยนหรือจับ ตอนนี้ที่รันไทม์หากเมธอดโอเวอร์โหลดจะพ่นE2ซึ่งก็คือE1ซูเปอร์คลาสแล้วล่ะก็ ... มันผิดมาก (ด้วยเหตุผลเดียวกันที่เราไม่สามารถพูดได้B myBObj = new A()) ดังนั้น Java จึงไม่อนุญาต ข้อยกเว้นที่ไม่ได้ตรวจสอบที่ส่งโดยเมธอดโอเวอร์โหลดต้องเหมือนกันคลาสย่อยหรือไม่มีอยู่จริง


คลาส Parent {void method () พ่น IndexOutOfBoundsException {System.out.println ("Parent method"); }} class Child ขยาย Parent {void method () พ่น RuntimeException {System.out.println ("Child method"); } ถ้าคลาสพาเรนต์โยนชายน์ของข้อยกเว้นรันไทม์และชายด์โยนข้อยกเว้นรันไทม์เอง ใช้ได้หรือไม่
abhiagNitk

1

เพื่อให้เข้าใจถึงปล่อยให้เรื่องนี้พิจารณาตัวอย่างที่เราได้เรียนMammalซึ่งได้กำหนดวิธีการที่จะอ่านไฟล์บางทำดำเนินการบางอย่างกับมันและกลับมาอินสแตนซ์ของคลาสreadAndGetMammal

class Mammal {
    public Mammal readAndGet() throws IOException {//read file and return Mammal`s object}
}

คลาสHumanขยายคลาสMammalและแทนที่readAndGetเมธอดเพื่อส่งคืนอินสแตนซ์Humanแทนอินสแตนซ์ของMammal.

class Human extends Mammal {
    @Override
    public Human readAndGet() throws FileNotFoundException {//read file and return Human object}
}

ในการโทรreadAndGetเราจะต้องจัดการIOExceptionเพราะมันเป็นข้อยกเว้นที่ตรวจสอบแล้วและสัตว์เลี้ยงลูกด้วยนมreadAndMethodกำลังขว้างมัน

Mammal mammal = new Human();
try {
    Mammal obj = mammal.readAndGet();
} catch (IOException ex) {..}

และเรารู้ว่าสำหรับคอมไพเลอร์mammal.readAndGet()จะได้รับการเรียกจากวัตถุของชั้นMammalแต่ในรันไทม์ JVM จะแก้ไขmammal.readAndGet()วิธีการเรียกร้องให้โทรจากชั้นเรียนHumanเพราะมีการถือครองmammalnew Human()

วิธีreadAndMethodจากMammalคือการขว้างปาIOExceptionและเนื่องจากเป็นคอมไพเลอร์ข้อยกเว้นที่ตรวจสอบแล้วจะบังคับให้เราจับได้ทุกครั้งที่เราเรียกreadAndGetบนmammal

ตอนนี้สมมติว่าreadAndGetในHumanกำลังโยนข้อยกเว้นที่ตรวจสอบอื่น ๆ เช่น Exception และเรารู้ว่าreadAndGetจะถูกเรียกจากอินสแตนซ์ของHumanbecause mammalis holdingnew Human()เป็นโฮลดิ้ง

เนื่องจากสำหรับคอมไพเลอร์เมธอดถูกเรียกใช้Mammalดังนั้นคอมไพเลอร์จะบังคับให้เราจัดการเท่านั้นIOExceptionแต่ในรันไทม์เรารู้ว่าเมธอดจะถูกขว้างExceptionข้อยกเว้นซึ่งไม่ได้รับการจัดการและโค้ดของเราจะแตกหากเมธอดส่งข้อยกเว้น

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

มีกฎอื่น ๆ เช่นกันที่เราต้องปฏิบัติตามในขณะที่ลบล้างวิธีการและคุณสามารถอ่านเพิ่มเติมเกี่ยวกับเหตุผลที่เราควรปฏิบัติตามกฎการแทนที่วิธีการเพื่อทราบเหตุผล


0

คำอธิบายใดที่เรากล่าวถึงด้านล่างนี้

class BaseClass {

    public  void print() {
        System.out.println("In Parent Class , Print Method");
    }

    public static void display() {
        System.out.println("In Parent Class, Display Method");
    }

}


class DerivedClass extends BaseClass {

    public  void print() throws Exception {
        System.out.println("In Derived Class, Print Method");
    }

    public static void display() {
        System.out.println("In Derived Class, Display Method");
    }
}

คลาส DerivedClass.java แสดงข้อยกเว้นเวลาคอมไพล์เมื่อเมธอดพิมพ์พ่น Exception, print () เมธอดของ baseclass ไม่ให้มีข้อยกเว้นใด ๆ

ฉันสามารถระบุสิ่งนี้กับความจริงที่ว่า Exception นั้นแคบกว่า RuntimeException อาจเป็น No Exception (ข้อผิดพลาด Runtime), RuntimeException และข้อยกเว้นลูก


0

วิธีการลบล้างของคลาสย่อยสามารถโยนได้เฉพาะข้อยกเว้นที่ตรวจสอบแล้วหลายรายการซึ่งเป็นคลาสย่อยของข้อยกเว้นที่ตรวจสอบของเมธอดของ superclass แต่ไม่สามารถโยนข้อยกเว้นที่ตรวจสอบหลายรายการที่ไม่เกี่ยวข้องกับข้อยกเว้นที่ตรวจสอบของเมธอดของ superclass


0

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

Java เป็นภาษาเก่าที่ออกแบบมาไม่ดี ภาษาสมัยใหม่ไม่มีข้อ จำกัด ดังกล่าว วิธีที่ง่ายที่สุดในการแก้ไขข้อบกพร่องนี้คือทำให้คลาสพื้นฐานของคุณthrow Exceptionเสมอ ลูกค้าสามารถโยนข้อยกเว้นที่เฉพาะเจาะจงมากขึ้นได้ แต่ทำให้คลาสพื้นฐานของคุณกว้างขึ้น


0

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

- เมื่อเมธอดระดับพาเรนต์ประกาศว่าไม่มีข้อยกเว้นดังนั้นเมธอดการลบล้างคลาสย่อยสามารถประกาศ ,

 1. No exception or
 2. Any number of unchecked exception
 3. but strictly no checked exception

- เมื่อเมธอดระดับผู้ปกครองประกาศข้อยกเว้นที่ไม่ได้ตรวจสอบแล้ววิธีการแทนที่คลาสลูกสามารถประกาศได้

 1. No exception or
 2. Any number of unchecked exception 
 3. but strictly no checked exception

- เมื่อเมธอดระดับพาเรนต์ประกาศข้อยกเว้นที่ตรวจสอบแล้วคลาสลูกจะสามารถประกาศได้

 1. No exception or
 2. Same checked exception or
 3. Sub-type of checked exception or
 4. any number of unchecked exception

ข้อสรุปข้างต้นทั้งหมดเป็นจริงแม้ว่าการรวมกันของข้อยกเว้นที่ตรวจสอบและไม่ได้ตรวจสอบจะถูกประกาศในเมธอด parent-class

อ้างอิง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.