문제

class Bouncy<T> extends Throwable {     
}
// Error: the generic class Bouncy<T> may not subclass java.lang.Throwable

지 않는 이유는 무엇 자바를 지원하는 일반 Throwables?

나는 형식 지우 복잡하게 어떤 일이지만,분명히 Java 얻으로 이미 많은 것,그래서 왜 밀어 그것을 하나 더 많은 수준의 허용 일반 Throwables 의 포괄적인 컴파일시 확인에 대한 잠재적인 문제가 있습니까?


나는 느낌과 같은 유형 삭제 인수가 오히 약하다.현재,우리는 할 수 없:

void process(List<String> list) {
}

void process(List<Integer> list) {
}

물론 우리는 얻을 수 없습니다.나 요구하지는 우리는 할 수 있어야 catch Bouncy<T1>Bouncy<T2> 에서 동일한 try 블록,하지만 우리가 사용하는 경우에는 연결이 끊긴 상황으로는 엄격한 컴파일 타임 시행 규칙(이는 매우 많은 방법 제네릭이 지금 작동),지 않을 실행할 수 있습니까?

도움이 되었습니까?

해결책

자바 언어 사양8.1.2 일반 클래스 및 유형 매개 변수:

이 제한은 Java Virtual Machine의 캐치 메커니즘이 비 게 니체 클래스에서만 작동하기 때문에 필요합니다.

개인적으로, 나는 그것이 우리가 제네릭의 혜택을 얻을 수 없기 때문이라고 생각합니다. catch 절. 우리는 글을 쓸 수 없습니다 catch (Bouncy<String> ex) 유형 삭제로 인해 우리가 쓰면 catch (Bouncy ex), 그것을 일반적으로 만드는 것은 쓸모가 없습니다.

다른 팁

삭제를 입력하십시오. 런타임 예외 유형에는 제네릭 정보가 없습니다. 따라서 당신 할 수 없다

} catch( Mistake<Account> ea) {
  ...
} catch( Mistake<User> eu) {
...
}

당신들 모두 할수있다 ~이다

catch( Mistake ea ) {
  ...
}

유형 지우기는 Java가 1.4에서 1.5로 이동했을 때 후진 호환성을 보존하기로 결정한 방법입니다. 많은 사람들이 불행했고 정당하게 그렇게했습니다. 그러나 배포 된 코드의 양을 염두에두고 1.4에서 행복하게 작동하는 코드를 깨는 것은 생각할 수 없었습니다.

짧은 대답 : 지름길을 삭감했기 때문에 지우기와 마찬가지로.

긴 답변 : 다른 사람들이 이미 지적했듯이, 삭제로 인해 "Catch MyException"사이의 런타임에 차이를 만들 수있는 방법은 없습니다.u003CString> "그리고"MyException을 잡아라u003CInteger> ".

하지만 그렇다고해서 일반적인 예외가 필요하지 않다는 의미는 아닙니다.. 제네릭이 제네릭 필드를 사용할 수 있기를 바랍니다! 그들은 단순히 일반적인 예외를 허용 할 수 있었지만 원시 상태에서만 잡을 수있었습니다 (예 : "Catch MyException").

물론, 이것은 제네릭을 더욱 복잡하게 만들 것입니다. 이것은 제네릭을 지우 겠다는 결정이 얼마나 나쁜지를 보여주는 것입니다. 현재 구문 설탕이 아닌 실제 제네릭 (RTTI)을 지원하는 Java 버전은 언제 가질 것입니까?

여전히 사용할 수 있습한 일반적 방법은 다음과 같습니다.

public class SomeException {
    private final Object target;

    public SomeException(Object target) {
        this.target = target;
    }

    public <T> T getTarget() {
        return (T) target;
    }
}

....

catch (SomeException e) {
    Integer target = e.getTarget();
}

라이 크리스티안의 대답이다.하는 동안 허용된 응답은 기술적으로 올바른(으니까 그것을 참조 JVM specs),크리스티안 Vasile 의 대답은 한 자격 심지어 도전에 제한이 있습니다.

거기에는 적어도 두 개의 인수를 내가 주의에서 이 질문에 답하게는 내가에 동의하지 않는 것이 반박.는 경우 인수에서 이러한 답변을 정확하,우리가 사용할 수 있는 이 인수의 공격에 제네릭을 다른 컨텍스트에서 그들이 어디에 사용되는 성공적으로 오늘입니다.


첫 번째 인수는 우리는 할 수 없이 사용:

catch (Exception<T1> e) {}

기 때문에 JVM 알지 못하는 방법 Exception<T1>.이 인수하는 것 또한 공격이 사용하여 제네릭의 기초하여,JVM 지 않을 사용하는 방법을 알 List<T1>:

List<T1> list;

인수,물론,그 사실을 잊어버 컴파일러 수행하는 유형을 삭제하고 그래서 JVM 이 필요하지 않을 처리하는 방법을 알 Exception<T1>.그것은 단순히 처리 Exception, 처럼,그것은 처리 List.

물론 우리가 할 수 없을 처리 catch(Exception<T1> e)catch(Exception<T2> e) 에서 동일한 시도/을 잡을 때의 삭제 유형,그러나,그것보다 더 나쁜으로 방법을 인수 또는 반환 값의 오늘:우리는 취급하지 않는 myMethod(List<T1>)myMethod(List<T2>) 오늘 중...(나는 반복 이러한 측면에서 두 번째로 반박이다.)


두 번째 인수가는 다음과 같습니다.우리는이 허용되지 않:

catch (Exception<T1> e) {}

기 때문에 이 작동하지 않을 것:

catch (Exception<T1> e) {}
catch (Exception<T2> e) {}

확인,다음 왜 허용하지 않다:

interface MyInterface {
    Comparable<Integer> getComparable();
}

기 때문에 이 이 작동하지 않는:

interface MyInterface {
    Comparable<Integer> getComparable();
    Comparable<String> getComparable();
}

나이:

interface MyInterface {
    void setComparable(Comparable<Integer> comparable);
}

기 때문에 이 이 작동하지 않는:

interface MyInterface {
    void setComparable(Comparable<Integer> comparable);
    void setComparable(Comparable<String> comparable);
}

다시 말해서,왜 허용하지 않 generics 에서 대부분의 경우?

이 두 번째 인수를 잊지만,우리할 수는 없이 사용되고 있는 일반 구성하는 그 삭제를 동일 아닌 일반적인 구문은 이러한 상황에서,우리는 여전히 그렇게 할 수 있습 다음 최고의 일과 용 제네릭만큼 유형 삭제하지 않을 동일한 유형.우리와 방법을 매개변수:우리가 사용할 수 있도록 제네릭이지만,불평 한 빨리 우리가 감지 중복된 서명한 후 유형에 지울 수 있습니다.음,우리가 할 수 있에 대해 동일한 것으로 예외 및 catch 블록...


결론적으로,나는 확장에 크리스티안의 대답이다.에 대한 일반적인 예외 클래스 를 사용하는 원료 종류에서 catch 블:

class MyException<T> {}
...
catch (MyException e) { // raw

Java 갈 수 있는 전체를 문제없이 길:

class MyException<T> {}
...
catch (MyException<Foo> e) {

다음은 몇 가지 사항이 있습니다 ~할 수 있다 하다:

  1. Throwables는 Throwable 자체에 유형 매개 변수가없는 한 일반 인터페이스를 구현할 수 있습니다.

    interface Bouncy<E> {
        // ...
    }
    class BouncyString extends Exception implements Bouncy<String> {
        // ...
    }

  2. throws 절은 유형 매개 변수를 참조 할 수 있습니다
    static <X extends Throwable> void
    throwIfInstanceOf(Throwable ex, Class<X> clazz) throws X {
        if (clazz.isInstance(ex)) throw clazz.cast(ex);
    }

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top