วิธีกำหนดคลาสยกเว้นที่กำหนดเองใน Java วิธีที่ง่ายที่สุด?


286

ฉันกำลังพยายามกำหนดคลาสข้อยกเว้นของตัวเองด้วยวิธีที่ง่ายที่สุดและนี่คือสิ่งที่ฉันได้รับ:

public class MyException extends Exception {}

public class Foo {
  public bar() throws MyException {
    throw new MyException("try again please");
  }
}

นี่คือสิ่งที่คอมไพเลอร์ Java พูดว่า:

cannot find symbol: constructor MyException(java.lang.String)

ฉันรู้สึกว่าคอนสตรัคนี้ต้องได้รับการสืบทอดมาจากjava.lang.Exceptionมันใช่ไหม?

คำตอบ:


402

ไม่คุณไม่ได้ "รับช่วง" คอนสตรัคเตอร์ที่ไม่ใช่ค่าเริ่มต้นคุณต้องกำหนดค่าที่จะใช้กับสตริงในคลาสของคุณ โดยทั่วไปคุณใช้super(message)ในตัวสร้างของคุณเพื่อเรียกใช้ตัวสร้างหลักของคุณ ตัวอย่างเช่นนี้:

public class MyException extends Exception {
    public MyException(String message) {
        super(message);
    }
}

58
@vulkanino: ไม่คอนสตรัคเตอร์เริ่มต้นถูกเพิ่มโดยคอมไพเลอร์สำหรับทุกคลาสที่กำหนดคอนสตรัคเตอร์ของมันเองไม่ได้ หากคุณกำหนดนวกรรมิกอย่างชัดเจนคุณจะไม่ได้รับค่าเริ่มต้นแม้ว่าจะมี superclass และถ้าคลาสของคุณไม่มีคอนสตรัคเตอร์คุณจะได้รับค่าเริ่มต้นแม้ว่าจะไม่มี superclass ก็ตาม
Michael Borgwardt

5
if your class has no constructor, you get the default even if the superclass does not have itส่วนสุดท้ายเป็นไปไม่ได้ยกเว้นว่า superclass มีตัวสร้างเริ่มต้นที่สามารถเข้าถึงคลาสนี้ได้ (อาจได้รับการป้องกันหรือป้องกันด้วยแพ็คเกจ) มิฉะนั้นคุณต้องเรียกอย่างชัดเจนว่าหนึ่งในผู้สร้างหลักมิฉะนั้นการรวบรวมจะล้มเหลว
Sean Patrick Floyd

43
กรุณาเพิ่มMyException(Throwable)และMyException(String, Throwable)การก่อสร้างที่จะต้องสนับสนุนข้อยกเว้นการผูกมัด
Danilo Piazzalunga

8
เกือบ 3 ปีต่อมาและไม่มีการเพิ่มสิ่งก่อสร้างพิเศษ :(
byxor

2
@BrandonIbbotson คุณหมายถึงอะไรโดย 'พวกเขา' และพวกเขาจะเพิ่มที่ไหน? หากสิ่งที่คุณหมายถึงโดย 'พวกเขา' คือตัวสร้าง superclass และ 'ที่ไหน' เป็น subclass แสดงว่าคุณผิด ตัวสร้าง Superclass ไม่ได้ถูกเพิ่มลงในคลาสย่อยโดยปริยาย นอกจากนี้ฉันไม่เห็นหัวข้ออื่นในประโยคก่อนหน้าเพื่อให้คำเหล่านั้นอ้างอิง
halil

90

ข้อยกเว้นที่กำหนดเองโดยทั่วไปที่ฉันกำหนดไว้เป็นดังนี้:

public class CustomException extends Exception {

    public CustomException(String message) {
        super(message);
    }

    public CustomException(String message, Throwable throwable) {
        super(message, throwable);
    }

}

ฉันยังสร้างเทมเพลตโดยใช้ Eclipse ดังนั้นฉันจึงไม่ต้องเขียนทุกสิ่งซ้ำแล้วซ้ำอีก


17
คุณสามารถขยายข้อยกเว้นเมื่อสร้างคลาสของคุณใน Eclipse และคุณจะได้รับตัวสร้างทั้งสี่ คุณไม่ต้องการเทมเพลต
jeremyjjbrown

เมื่อใดที่เราควรใช้ Consutructor ที่สองแทนอันแรก?
ZhaoGang

61

หากคุณใช้ไดอะล็อกคลาสใหม่ใน Eclipse คุณสามารถตั้งค่าฟิลด์ Superclass เป็นjava.lang.Exceptionและตรวจสอบ "Constructors from superclass" และมันจะสร้างสิ่งต่อไปนี้:

package com.example.exception;

public class MyException extends Exception {

    public MyException() {
        // TODO Auto-generated constructor stub
    }

    public MyException(String message) {
        super(message);
        // TODO Auto-generated constructor stub
    }

    public MyException(Throwable cause) {
        super(cause);
        // TODO Auto-generated constructor stub
    }

    public MyException(String message, Throwable cause) {
        super(message, cause);
        // TODO Auto-generated constructor stub
    }

}

เพื่อตอบคำถามต่อไปนี้เกี่ยวกับการไม่เรียกsuper()ใช้ตัวสร้างค่าเริ่มต้น Oracle มีคำสั่งดังต่อไปนี้ :

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


1
ทำไมมันไม่จำเป็นสำหรับผู้สร้างเริ่มต้นที่จะเรียกsuper()?
ceving


22

เหตุผลนี้อธิบายไว้ในบทความการสืบทอดของแพลตฟอร์ม Java ซึ่งกล่าวว่า:

"คลาสย่อยสืบทอดสมาชิกทั้งหมด (ฟิลด์, เมธอด, และคลาสที่ซ้อนกัน) จาก superclass ของมันคอนสตรัคเตอร์ไม่ใช่สมาชิกดังนั้นพวกเขาจึงไม่ได้รับการสืบทอดโดยคลาสย่อย แต่ตัวสร้างของซูเปอร์คลาสสามารถเรียกใช้จากคลาสย่อยได้"


19
package customExceptions;

public class MyException extends Exception{

    public MyException(String exc)
    {
        super(exc);
    }
    public String getMessage()
    {
        return super.getMessage();
    }
}

import customExceptions.MyException;

public class UseCustomException {

    MyException newExc=new MyException("This is a custom exception");

    public UseCustomException() throws MyException
    {
        System.out.println("Hello Back Again with custom exception");
        throw newExc;       
}

    public static void main(String args[])
    {
        try
        {
            UseCustomException use=new UseCustomException();
        }
        catch(MyException myEx)
        {
            System.out.println("This is my custom exception:" + myEx.getMessage());
        }
    }
}

สิ่งนี้จะกลับมา?
user1876508

มันจะพิมพ์ออกมา "Hello Back อีกครั้งด้วยข้อยกเว้นที่กำหนดเอง" ซึ่งมาจากตัวสร้างสำหรับ UseCusomException ข้อยกเว้นจะถูกโยนทิ้งแล้วติดอยู่ในหลักซึ่งจะพิมพ์ออกมา "นี่คือข้อยกเว้นที่กำหนดเองของฉัน: นี่คือข้อยกเว้นที่กำหนดเอง"
ThePerson

2

คลาสข้อยกเว้นมีสองตัวสร้าง

  • public Exception() - สิ่งนี้สร้างข้อยกเว้นโดยไม่มีข้อมูลเพิ่มเติมความผิดปกติของข้อยกเว้นมักจะอนุมานจากชื่อคลาส
  • public Exception(String s) - สร้างข้อยกเว้นพร้อมข้อความแสดงข้อผิดพลาดที่ระบุข้อความรายละเอียดคือสตริงที่อธิบายถึงเงื่อนไขข้อผิดพลาดสำหรับข้อยกเว้นเฉพาะนี้

3
ที่จริงตั้งแต่ Java 1.4 มีสองก่อสร้างงานเพิ่มเติมได้ที่: และpublic Exception(Throwable) public Exception(String, Throwable)พวกเขามีความจำเป็นเพื่อการสนับสนุนอย่างถูกต้องข้อยกเว้นการผูกมัด
Danilo Piazzalunga

@DaniloPiazzalunga เห็นด้วยกับคุณ แหล่งที่มา: สร้างข้อมูลอย่างย่อ docs.oracle.com/javase/1.5.0/docs/api/java/lang/Exception.html
KNU

0

ถ้าคุณสืบทอดจาก Exception คุณต้องระบุ Constructor ที่รับค่าสตริงเป็นพารามิเตอร์ (ซึ่งจะมีข้อความแสดงข้อผิดพลาด)


ฉันคิดว่าคุณควรเพิ่มเหตุผลด้วย
Jigar Joshi

3
จริงๆแล้วมันไม่ถูกต้อง หากรหัสของคุณใช้ Constructor ที่มีอาร์กิวเมนต์ String ตัวเดียวคุณต้องประกาศ อย่างไรก็ตามคลาสย่อยของข้อยกเว้นสามารถกำหนดได้โดยไม่มีตัวสร้างที่ชัดเจน ... เนื่องจากข้อยกเว้นมีตัวสร้างแบบไม่ args
สตีเฟ่นซี

0

และอย่าลืมวิธีที่ง่ายที่สุดในการโยนข้อยกเว้น (คุณไม่จำเป็นต้องสร้างชั้นเรียน)

if (rgb > MAX) throw new RuntimeException("max color exceeded");
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.