Programming

Java가 Throwable의 일반 서브 클래스를 허용하지 않는 이유는 무엇입니까?

procodes 2020. 6. 21. 21:03
반응형

Java가 Throwable의 일반 서브 클래스를 허용하지 않는 이유는 무엇입니까?


Java Language Sepecification , 3 판 에 따르면 :

일반 클래스가의 직접 또는 간접 서브 클래스 인 경우 컴파일 타임 오류입니다 Throwable.

이 결정이 내려진 이유를 이해하고 싶습니다. 일반적인 예외의 문제점은 무엇입니까?

(내가 아는 한 제네릭은 단순히 컴파일 타임 구문 설탕이며 파일 Object에서 어쨌든 번역 .class되므로 제네릭 클래스를 효과적으로 선언하는 것은 마치 마치 모든 것이 인 것처럼 효과적 Object입니다. 틀린 경우 수정하십시오 .)


마크가 말했듯이 유형을 수정할 수 없으므로 다음과 같은 경우에 문제가됩니다.

try {
   doSomeStuff();
} catch (SomeException<Integer> e) {
   // ignore that
} catch (SomeException<String> e) {
   crashAndBurn()
}

모두 SomeException<Integer>SomeException<String>동일한 유형으로 지워집니다, JVM이 예외 인스턴스를 구별 할 방법과 어떤 얘기하는 것이 방법이 없습니다 catch실행되어야 블록.


다음은 예외 사용 방법에 대한 간단한 예입니다.

class IntegerExceptionTest {
  public static void main(String[] args) {
    try {
      throw new IntegerException(42);
    } catch (IntegerException e) {
      assert e.getValue() == 42;
    }
  }
}

TRy 문의 본문은 주어진 값으로 예외를 처리하며 이는 catch 절에 의해 포착됩니다.

반대로, 새 예외에 대한 다음 정의는 매개 변수화 된 유형을 작성하므로 금지됩니다.

class ParametricException<T> extends Exception {  // compile-time error
  private final T value;
  public ParametricException(T value) { this.value = value; }
  public T getValue() { return value; }
}

위의 컴파일을 시도하면 오류가보고됩니다.

% javac ParametricException.java
ParametricException.java:1: a generic class may not extend
java.lang.Throwable
class ParametricException<T> extends Exception {  // compile-time error
                                     ^
1 error

이 예외는 유형을 수정할 수 없기 때문에 이러한 예외를 포착하려는 거의 모든 시도가 실패해야하기 때문에 합리적입니다. 예외의 일반적인 사용은 다음과 같습니다.

class ParametricExceptionTest {
  public static void main(String[] args) {
    try {
      throw new ParametricException<Integer>(42);
    } catch (ParametricException<Integer> e) {  // compile-time error
      assert e.getValue()==42;
    }
  }
}

catch 절의 유형을 확인할 수 없으므로 허용되지 않습니다. 이 글을 쓰는 시점에서 Sun 컴파일러는 다음과 같은 경우에 일련의 구문 오류를보고합니다.

% javac ParametricExceptionTest.java
ParametricExceptionTest.java:5: <identifier> expected
    } catch (ParametricException<Integer> e) {
                                ^
ParametricExceptionTest.java:8: ')' expected
  }
  ^
ParametricExceptionTest.java:9: '}' expected
}
 ^
3 errors

예외는 매개 변수가 될 수 없으므로 구문이 제한되어 형식이 다음 매개 변수없이 식별자로 작성되어야합니다.


본질적으로 나쁜 방식으로 설계 되었기 때문입니다.

이 문제는 깨끗한 추상 디자인을 방지합니다.

public interface Repository<ID, E extends Entity<ID>> {

    E getById(ID id) throws EntityNotFoundException<E, ID>;
}

제네릭에 대한 catch 절이 실패한다는 사실은 그에 대한 변명이 아닙니다. 컴파일러는 캐치 절 내에서 Throwable을 확장하거나 제네릭을 허용하지 않는 구체적인 제네릭 형식을 허용하지 않을 수 있습니다.


Generics are checked at compile-time for type-correctness. The generic type information is then removed in a process called type erasure. For example, List<Integer> will be converted to the non-generic type List.

Because of type erasure, type parameters cannot be determined at run-time.

Let's assume you are allowed to extend Throwable like this:

public class GenericException<T> extends Throwable

Now let's consider the following code:

try {
    throw new GenericException<Integer>();
}
catch(GenericException<Integer> e) {
    System.err.println("Integer");
}
catch(GenericException<String> e) {
    System.err.println("String");
}

Due to type erasure, the runtime will not know which catch block to execute.

Therefore it is a compile-time error if a generic class is a direct or indirect subclass of Throwable.

Source: Problems with type erasure


I would expect that it's because there's no way to guarantee the parameterization. Consider the following code:

try
{
    doSomethingThatCanThrow();
}
catch (MyException<Foo> e)
{
    // handle it
}

As you note, parameterization is just syntactic sugar. However, the compiler tries to ensure that parameterization remains consistent across all references to an object in compilation scope. In the case of an exception, the compiler has no way to guarantee that MyException is only thrown from a scope that it is processing.

참고URL : https://stackoverflow.com/questions/501277/why-doesnt-java-allow-generic-subclasses-of-throwable

반응형

'Programming' 카테고리의 다른 글

SQL Server NOLOCK 및 조인  (0) 2020.06.21
ASP.NET 임시 파일 정리  (0) 2020.06.21
부드러운 GPS 데이터  (0) 2020.06.21
Build.scala, % 및 %% 기호 의미  (0) 2020.06.21
너비 우선 검색을 재귀 적으로 수행  (0) 2020.06.21