재정의 메서드가 재정의 메서드보다 더 넓은 예외를 발생시킬 수 없는 이유는 무엇입니까?
나는 Kathe sierra의 SCJP 6 책을 읽다가 오버라이드 방식으로 예외를 두는 것에 대한 설명을 접했다.나는 그것을 전혀 이해하지 못했다.누가 그걸 설명해 줄 수 있나요?
재정의 메서드는 재정의 메서드에 의해 선언된 예외보다 더 크거나 더 넓은 체크된 예외를 슬로우해서는 안 됩니다.예를 들어 FileNotFoundException을 선언하는 메서드는 FileNotFoundException의 하위 클래스가 아니면 SQLException, Exception 또는 기타 런타임 이외의 예외를 선언하는 메서드에 의해 재정의될 수 없습니다.
즉, 메서드가 특정 예외를 슬로우한다고 선언한 경우 서브클래스의 덮어쓰기 메서드는 해당 예외 또는 해당 서브클래스를 슬로우한다고 선언할 수 있습니다.예를 들어 다음과 같습니다.
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
}
ifB
SQLException
로 잡을 수 은 ''를입니다.왜냐하면 당신은 의 인스턴스를 참조하고 있기 때문입니다.B
그 슈퍼클래스에 의해 -A
「」, 「」의의 서브 클래스IOException
를 처리하는 절(구 또는 슬로우)에 의해 처리됩니다.IOException
개체를 슈퍼클래스로 참조할 수 있어야 하는 규칙은 Liskov 대체 원칙입니다.
선택되지 않은 예외는 어디서나 발생할 수 있으므로 이 규칙의 적용을 받지 않습니다.필요에 따라 문서 형식으로 throws 구에 체크되지 않은 예외를 추가할 수 있지만 컴파일러는 이에 대해 아무것도 강제하지 않습니다.
덮어쓰기 메서드는 덮어쓰기 메서드가 예외를 선언하는지 여부에 관계없이 선택되지 않은(런타임) 예외를 슬로우할 수 있습니다.
예:
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()");
}
}
자바 구문설계의 실패라고 생각합니다.다형성은 예외 처리의 사용을 제한해서는 안 됩니다.실제로 다른 컴퓨터 언어에서는 그렇지 않습니다(C#).
또한 메서드는 보다 복잡하고 새로운 예외를 발생시킬 가능성이 높아지도록 보다 전문화된 서브클래스로 덮어쓰게 된다.
이 답변은 오래된 질문에 대해 다음과 같이 대답합니다. 왜냐하면 어떤 답변도 덮어쓰기 방법이 아무것도 던지지 않는다는 사실을 말해주지 않기 때문입니다. 다시 덮어쓰기 방법이 던질 수 있는 것은 다음과 같습니다.
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) 오버리든 메서드의 서브클래스의 슬로우 예외
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) 런타임 사용슬로우 예외는 필요하지 않다.
Runtime이 있을 수 있습니다.예외는 던지든 안 던지든 컴파일러는 불평하지 않습니다.런타임예외는 체크되지 않습니다.캐치되지 않은 경우 선택한 예외만 슬로우 형태로 표시되어야 합니다.
이를 설명하기 위해 다음 사항을 고려하십시오.
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()는 FileNotFoundException보다 넓은 IOException을 슬로우하기 때문에 컴파일 오류가 발생합니다.
이 문제를 해결하려면 다음과 같이 적습니다.
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이 느려질 수 있는 경우 클라이언트의 코드는 nolonger가 맞습니다.
선택되지 않은 예외를 사용하면 이러한 문제를 방지할 수 있습니다.(그것은 철학적 문제이기 때문에 제안하거나 하지 말 것을 제안하는 것이 아닙니다.
인터뷰 질문을 받겠습니다.Null Pointer를 슬로우하는 메서드가 있습니다.슈퍼클래스 예외입니다.Runtime을 슬로우하는 메서드로 덮어쓸 수 있습니까?예외?
이 질문에 답하려면 체크되지 않은 예외 및 체크된 예외에 대해 알려 주십시오.
체크된 예외는 Basic try-catch-finally Exception Handling의 설명에 따라 명시적으로 검출 또는 전파해야 합니다.선택되지 않은 예외에는 이 요건이 없습니다.그들은 잡히거나 버려졌다고 선언할 필요가 없다.
Java에서 예외를 체크하여 java.lang을 확장.예외 클래스선택되지 않은 예외는 java.lang을 확장합니다.Runtime Exception 입니다.
퍼블릭 클래스 Null Pointer예외가 실행 시간을 확장예외.
선택되지 않은 예외는 java.lang을 확장합니다.Runtime Exception 입니다.이것이 바로 Null Pointer의 이유예외는 체크되지 않은 예외입니다.
예를 들어 보겠습니다.예 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);
}
}
}
프로그램의 컴파일에 실패한다.따라서 Checked 예외를 사용할 때는 주의해야 합니다.
예를 들어 메서드 M1 슬로인 E1의 슈퍼 클래스 A와 메서드 M2가 M1보다 우선하는 메서드 M2에서 파생된 클래스 B가 있다고 가정합니다. M2는 E1과 다르거나 덜 특수화된 어떤 것도 던질 수 없습니다.
다형성 때문에 클래스 A를 사용하는 클라이언트는 B를 A인 것처럼 취급할 수 있어야 합니다.Inharance === > Is-a (B is-a A).M1이 이 체크된 예외를 발생시킨다고 선언한 것처럼 클래스 A를 취급하는 이 코드가 예외 E1을 처리하고 있었는데 다른 유형의 예외가 발생했다면 어떻게 해야 할까요?M1이 IOException을 투척하고 있는 경우, M2는 FileNotFoundException을 그대로 투척할 수 있습니다.A의 클라이언트는 문제없이 대응할 수 있었습니다.예외가 더 넓으면 A의 클라이언트는 이 사실을 알 수 없기 때문에 잡을 기회가 없습니다.
java.lang은.예외는 java.lang을 확장합니다.던질 수 있습니다.java.ioFileNotFoundException은 java.lang을 확장합니다.예외.어떤 메서드가 java.io을 슬로우 했을 경우.FileNotFoundException은 덮어쓰기 메서드에서 FileNotFoundException보다 높은 것을 계층 위로 던질 수 없습니다.예를 들어 java.lang은 던질 수 없습니다.예외.단, FileNotFoundException의 서브클래스를 던질 수 있습니다.단, 덮어쓰기 메서드로 FileNotFoundException을 처리해야 합니다.코드를 만들어서 시도해 보세요!
규칙이 있기 때문에 특정성을 확장함으로써 원래 슬로우 선언을 잃지 않습니다.다형성은 슈퍼클래스에서 오버라이드 메서드를 호출할 수 있음을 의미합니다.
재정의 메서드는 재정의 메서드에 의해 선언된 예외보다 더 크거나 더 넓은 체크된 예외를 슬로우해서는 안 됩니다.
예:
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
}
}
아래의 설명에 귀속되는 것은 무엇입니까?
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");
}
}
Class Derived Class.java는 baseclass의 print 메서드가 Exception, print() 메서드가 예외를 슬로우하지 않으면 컴파일 시간 예외를 슬로우합니다.
이는 런타임보다 예외가 좁기 때문이라고 볼 수 있습니다.예외, 예외 없음(런타임 오류), 런타임 중 하나일 수 있습니다.예외 및 그 하위 예외
재정의 메서드는 재정의 메서드에 의해 선언된 예외보다 더 크거나 더 넓은 체크된 예외를 슬로우해서는 안 됩니다.
즉, 기존 메서드를 덮어쓸 때 이 오버로드된 메서드가 느려지는 예외는 원래 메서드가 느려지는 예외 또는 해당 서브클래스와 같아야 합니다.
선택된 모든 예외가 처리되는지 여부를 확인하는 작업은 실행 시간이 아닌 컴파일 시간에 수행됩니다.따라서 Java 컴파일러는 컴파일 시 오버라이드된 메서드가 실행하는 예외 유형을 확인합니다.어떤 오버라이드된 메서드가 실행될지는 런타임에만 결정할 수 있기 때문에 어떤 종류의 예외를 잡아야 하는지 알 수 없습니다.
예
수업이 요.A
그 「 」B
A
가 m1
클래스 ★★★★★B
이 (「이 메서드」라고 ).m2
혼동을 피하기 위해). 그럼 이제 ㅇㅇㅇㅇ, ㅇㅇㅇ, 이렇게 해 볼까요?m1
E1
, , , , 입니다.m2
E2
, 「」)E1
을 사용하다, 그럼 요?
A myAObj = new B();
myAObj.m1();
:m1
의 호출에 지나지 않는다.m2
에, 「」와 혼동하지 주세요.m1
★★★★★★★★★★★★★★★★★」m2
예에서는 를 위한 이 예에서는 단지 차별화를 위한 것입니다...을 사용하다시 하는 모든 그그 but but Java 컴classclassclassclassclassclassclassclass but butclass ( Class ) 。A
이 경우) 메서드가 존재하는지 확인하고 프로그래머가 처리하기를 기대합니다. 잡히거나 당연하다.E1
가 " "을(를) "E2
, 「」)E1
슈퍼클래스는는 '우리'라고 말할 수 ).그것은 매우 잘못되어 있습니다(같은 이유로 우리는 말할 수 없습니다).B myBObj = new A()
)따라서 Java에서는 허용되지 않습니다.오버로드된 메서드에 의해 발생하는 체크되지 않은 예외는 동일하거나 서브클래스 또는 존재하지 않아야 합니다.
하기 위해서 수업을 Mammal
「 」를 정의합니다.readAndGet
, 및 반환 Mammal
.
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
왜냐면mammal
보류중new Human()
.
방법readAndMethod
부터Mammal
던지고 있다IOException
체크된 예외 컴파일러이기 때문에 호출할 때마다 강제로 캐치합니다.readAndGet
에mammal
자, 이제...readAndGet
에Human
기타 체크된 예외를 발생시키고 있습니다.예외로 알고 있습니다.readAndGet
의 인스턴스에서 호출됩니다.Human
왜냐면mammal
보류중new Human()
.
컴파일러의 경우 메서드가 호출되기 때문입니다.Mammal
로 '만'을 IOException
는 방법이 던질 이라는 것을 있습니다.Exception
이 예외는 처리되지 않으며 메서드에서 예외가 발생하면 코드가 끊어집니다.
그렇기 때문에 컴파일러 레벨 자체에서 차단되고 JVM에 의해 처리되지 않기 때문에 새로운 체크 예외나 광범위한 체크 예외가 허용되지 않습니다.
메서드를 덮어쓸 때 따라야 하는 다른 규칙도 있습니다.그 이유를 알아보려면 메서드 덮어쓰기 규칙을 따라야 하는 이유에 대한 자세한 내용은 "Why We Should Follow Method Overriding Rules 。
하위 클래스의 재정의 메서드는 슈퍼 클래스의 메서드에서 선택한 예외의 하위 클래스인 여러 개의 선택된 예외만 던질 수 있지만 슈퍼 클래스의 메서드에서 선택한 예외와 관련이 없는 여러 개의 선택된 예외는 던질 수 없습니다.
Java는 클라이언트가 포착된 내용을 제한할 것으로 가정하기 때문에 상위 클래스의 예외를 제한할 수 있습니다.IMHO 고객은 향후 유연성을 필요로 할 수 있기 때문에, 이 「기능」을 사용하지 말아 주세요.
자바는 설계가 엉성하게 된 오래된 언어이다.현대 언어에는 그런 제한이 없습니다. 가장 입니다.throw Exception
는 보다 할 수 는 매우.클라이언트는 보다 구체적인 예외를 설정할 수 있지만 기본 클래스를 매우 폭넓게 만들 수 있습니다.
재정의된 메서드에 대한 검사 및 선택되지 않은 예외 처리 규칙
parent-class 메서드가 예외를 선언하지 않은 경우, child-class overriding 메서드는 다음과 같이 선언할 수 있습니다.
1. No exception or
2. Any number of unchecked exception
3. but strictly no checked exception
parent-class 메서드가 체크되지 않은 예외를 선언하면 child-class overriding-method는 다음과 같이 선언할 수 있습니다.
1. No exception or
2. Any number of unchecked exception
3. but strictly no checked exception
parent-class 메서드가 체크된 예외를 선언하면 child-class overriding-method는 다음과 같이 선언할 수 있습니다.
1. No exception or
2. Same checked exception or
3. Sub-type of checked exception or
4. any number of unchecked exception
위의 모든 결론은 parent-class' 메서드에서 on/off 예외의 조합이 선언되어도 true입니다.
덮어쓰기 메서드는 다음과 같이 던질 수 있습니다(그렇지만 그럴 필요는 없습니다).
체크되지 않은 것
그리고.
오버라이드된 메서드의 공변 유형(동일 또는 익스텐더)인 선택된 예외만 해당됩니다.
다음의 3개의 스테이트먼트를 검토해 주세요.
- 오버로드된 메서드는 인수 목록 I을 변경해야 합니다.메서드가 과부하되면 반환 유형 I이 변경될 수 있습니다.Overloaded 메서드가 광범위한 체크된 예외를 선언할 수 있음 true를 모두 선택합니다.
언급URL : https://stackoverflow.com/questions/5875414/why-cant-overriding-methods-throw-exceptions-broader-than-the-overridden-method
'programing' 카테고리의 다른 글
기존 테이블에 외부 키 추가 (0) | 2023.01.03 |
---|---|
Python의 Generators와 Iterators의 차이점 (0) | 2023.01.03 |
jQuery Data vs Attr? (0) | 2023.01.03 |
sqlite3.프로그래밍 오류:제공된 바인딩 수가 잘못되었습니다.현재 스테이트먼트에서는 1을 사용하고 있으며 74가 제공되고 있습니다. (0) | 2022.12.29 |
티멜리프:연결 - 식으로 구문 분석할 수 없습니다. (0) | 2022.12.29 |