Java는 왜 Throwable의 범용 서브클래스를 허용하지 않는가?
Java Language Sepecification에 따르면 제3판:
나는 왜 이 결정이 내려졌는지 이해하고 싶다.일반적인 예외에 무슨 문제가 있습니까?
타임됩니다.또한 번역됩니다.Object
anyway anyway the the the .class
즉 은, 그이 「」, 「」, 「」, 「」, 「」, 「」, 「」, 「」라고 하는 것과 같습니다.Object
))))))) 。
마크의 설명대로 타입은 재작성할 수 없습니다.이것은 다음과 같은 경우에 문제가 됩니다.
try {
doSomeStuff();
} catch (SomeException<Integer> e) {
// ignore that
} catch (SomeException<String> e) {
crashAndBurn()
}
다.SomeException<Integer>
★★★★★★★★★★★★★★★★★」SomeException<String>
되어 있기 수 어떤 JVM이 어떤 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>;
}
제네릭스를 위한 캐치 조항이 실패한다는 사실이 입증되지 않았다는 것은 그것에 대한 변명이 없다.컴파일러는 단순히 슬로우 가능 또는 캐치 구 내의 제네릭스를 확장하는 구체적인 제네릭 유형을 허용하지 않을 수 있습니다.
제네릭은 컴파일 시에 타입이 올바른지 여부를 확인합니다.그런 다음 일반 유형 정보는 유형 삭제라고 하는 프로세스에서 제거됩니다.예를들면,List<Integer>
non-timeout 타입으로 변환됩니다.List
.
유형 삭제로 인해 런타임에 유형 매개 변수를 확인할 수 없습니다.
예를 들어, 당신이 다음 단계를 연장하는 것이 허용된다고 가정해 봅시다.Throwable
다음과 같습니다.
public class GenericException<T> extends Throwable
이제 다음 코드를 살펴보겠습니다.
try {
throw new GenericException<Integer>();
}
catch(GenericException<Integer> e) {
System.err.println("Integer");
}
catch(GenericException<String> e) {
System.err.println("String");
}
유형 삭제로 인해 실행 시 어떤 catch 블록을 실행할지 알 수 없습니다.
따라서 일반 클래스가 Throwable의 직접 또는 간접 서브 클래스인 경우 컴파일 시 오류가 발생합니다.
출처: 유형 삭제 문제
파라메타화를 보장할 방법이 없기 때문이라고 생각합니다.다음 코드를 고려합니다.
try
{
doSomethingThatCanThrow();
}
catch (MyException<Foo> e)
{
// handle it
}
아시다시피 파라미터화는 통사적인 설탕일 뿐입니다.그러나 컴파일러는 컴파일 범위 내의 오브젝트에 대한 모든 참조에서 파라미터화가 일관되게 유지되도록 합니다.예외의 경우 컴파일러는 MyException이 처리 중인 범위에서만 느려지는 것을 보증할 수 없습니다.
질문과는 그다지 관련이 없지만, 정말 원하는 것은inner class
을 확장하다Throwable
선언할 수 있다static
이것은, 다음의 경우에 적용할 수 있습니다.Throwable
는 논리적으로 인클로징클래스와 관련되어 있지만 해당 인클로징클래스의 특정 범용 타입과는 관계가 없습니다.선언함으로써static
, 이것은 인클로징 클래스의 인스턴스에 바인드 되어 있지 않기 때문에, 문제는 해소됩니다.
다음의 예(인정적으로는 그다지 좋지 않습니다)는, 이것을 나타내고 있습니다.
/** A map for <String, V> pairs where the Vs must be strictly increasing */
public class IncreasingPairs<V extends Comparable<V>> {
private final Map<String, V> map;
public IncreasingPairs() {
map = new HashMap<>();
}
public void insertPair(String newKey, V value) {
// ensure new value is bigger than every value already in the map
for (String oldKey : map.keySet())
if (!(value.compareTo(map.get(oldKey)) > 0))
throw new InvalidPairException(newKey, oldKey);
map.put(newKey, value);
}
/** Thrown when an invalid Pair is inserted */
public static class InvalidPairException extends RuntimeException {
/** Constructs the Exception, independent of V! */
public InvalidPairException(String newKey, String oldKey) {
super(String.format("Value with key %s is not bigger than the value associated with existing key %s",
newKey, oldKey));
}
}
}
자세한 것은, docs.oracle.com 를 참조해 주세요.
언급URL : https://stackoverflow.com/questions/501277/why-doesnt-java-allow-generic-subclasses-of-throwable
'programing' 카테고리의 다른 글
prop 인수가 null인 경우 기본값 사용 (0) | 2022.07.14 |
---|---|
Vue.js 애플리케이션 내에서 로컬 버전의 데이터 개체를 사용하는 방법 (0) | 2022.07.14 |
C: clock()을 사용하여 멀티 스레드 프로그램의 시간을 측정합니다. (0) | 2022.07.14 |
vue 템플릿에서 Typescript 정적 메서드 사용 (0) | 2022.07.14 |
makefile:4:** 구분자가 없습니다.이제 그만 (0) | 2022.07.14 |