2010-11-26 2 views
3

I 인터페이스와이 인터페이스를 구현하는 AB 클래스가 있다고 가정합니다. A에이 인터페이스의 f 메서드를 구현하면 예외 집합이 하나 throw되고 B에 구현하면 다른 집합이 throw됩니다. 이러한 예외의 유일한 조상은 java.lang.Exception입니다. 이 경우에 java.lang.Exception을 던지는 것은 f이라고 말하는 것이 합리적입니까? 다른 대안들?인터페이스 메소드의 throws 절에 무엇을 넣을 까?

내가 묻는 이유는 한편으로는 java.lang.Exception이 나에게 너무 일반적으로 보이고 모든 예외를 나열하는 다른 손은 가능한 다른 구현을 고려할 때 비현실적인 것처럼 보입니다.

예 :

interface I { 
    void f() throws Exception; 
} 

class A implements I { 
    public void f() throws IOException {} 
} 

class B implements I { 
    public void f() throws InterruptedException {} 
} 
+4

확인 된 예외가 일반적으로 언어 디자인에서 실패한 실험으로 간주되는 가장 큰 이유를 발견했습니다. –

+2

@Michael Borgwardt - 귀하의 의견과 downvote는 주제와 관련이 없습니다. –

답변

13

인터페이스를 사용하는 이유는 구현 세부 사항을 추상화하는 것입니다.

이러한 예외가 발생하면 구현 세부 정보가 노출 될 수 있으므로이를 추상화해야합니다.

아마도 새로운 예외를 정의하는 것이 가장 좋습니다. 그런 다음에 대해 알고있는 예외를 포착하고 대신 새로운 예외를 슬로우 F()의 각 구현은 당신이 줄 수 있도록 :

interface I { 
    void f() throws MyException; 
} 

class A implements I { 
    public void f() throws MyException { 
     try { 
      ... 
     } catch (IOException e) { 
      throw new MyException(e); 
     } 
    } 
} 

class B implements I { 
    public void f() throws MyException { 
     try { 
      ... 
     } catch (InterruptedException e) { 
      throw new MyException(e); 
     } 
    } 
} 

를 구현 예외를 랩으로, 당신은 여전히 ​​발신자에와 있음을 노출하고 원격 메소드를 호출 할 때 당신을 물 수 있습니다. 이 경우 유용한 정보를 일반적인 방법으로 반환하려면 더 많은 작업을해야합니다.

편집
올바른 접근 방식에 대해 계속 분쟁이 약간있는 것으로 보인다.

I instanceOfI = getI(); 
try { 
    instanceOfI.f(); 
} 
catch (/* What should go here ? */) 

그것은 catch 블록에 넣어 좋은 예외 클래스입니다 무엇을 내려 오는 : 우리가 F()를 호출 할 때처럼

, 우리는 코드가 필요합니다.
OP의 원래 코드를 사용하면 Exception을 잡을 수 있으며 요구 사항에 따라 어떤 하위 클래스가 있는지 확인할 수도 있습니다. 또는 각 하위 클래스를 개별적으로 catch 할 수는 있지만 새 구현에서 다른 예외가 발생하면 catch 블록을 추가해야합니다.

런타임 예외를 사용하는 경우 예외가 발생할 가능성을주지 않고 호출자 메소드로 예외 처리를 연기 할 수 있다는 점을 제외하고는 런타임 예외를 많이 사용합니다.

새로운 포장 된 예외 사용 제안을 사용한 경우 MyException을 붙잡고 추가 정보가 있는지 확인해야합니다. 이것은 본질적으로 Exception을 사용하는 것과 매우 흡사하게되지만, 목적에 맞출 수있는 bespoke 예외를 갖는 제한된 이익을 위해 추가 작업이 필요합니다.

+0

+1 나는 그것이가는 길이라고 생각한다. 자바에서는 새로운 클래스를 만들어야합니다. – milan

+0

+1 인터페이스가 일반 '예외'를 ​​던지라고 제안하지는 않지만 – Armand

+0

오프 주제 : "구현 세부 정보를 추상화합니다"누구로부터? 'class A' 또는'class B'의 사용자입니까? 내가 인터페이스의 하나의 시나리오를 취하면,'interface FilenameFilter'를 사용하고자하는 모든 사용자는 자신의 클래스를 사용하기 전에 구현해야합니다. 이 인터페이스를 사용하기 위해 다른 사람이 먼저 구현할 필요가 없습니다. 나는 "인터페이스는 주어진 계약을 가진 구체적인 하위 클래스의 주변 장치 (코어가 아닌) 기능의 집합체"라고 말할 것입니다. – overexchange

1

당신은 단지 예외를 선언 할 수 당신은 당신이 괜찮은 IDE를 사용하는 경우, 그것은 당신을 위해이 문제를 해결합니다

void f() throws IOException, InterruptedException; 

던져. 메소드에서 예외를 던지면 IDE는 메소드 절과 인터페이스에 옵션을 추가합니다.

+2

나중에 다른 것을 던지는 구현을 하나 더 추가하면 어떻게 될까요? – vitaut

+0

+1 무작위 downvote. –

3

약간 뒤로 보입니다. 당신은 당신의 인터페이스와 관련이 있을지도 모르는 특정 예외를 던지거나 전혀 던지지 말아야합니다. 일반적인은 아니지만 공통된 Exception 클래스를 래핑하도록 구현을 변경하십시오. 이 문제를 처리 할 수없는 경우 RuntimeException을 사용하여 구현에서 예외를 래핑 할 수 있습니다.

+0

RuntimeException을 제안한 +1 –

+2

@ 마이클 : 체크/체크되지 않은 예외 토론에 암시하는 것은 질문에서 제기 된 문제와는 완전히 관련이 없다고 생각합니다. –

+1

@Michael Borgwardt -이 경우 RuntimeException을 던지는 것은 매우 나쁜 생각입니다. 이것은 인터페이스가 던진 예외를 선언하는 방법 일뿐입니다. 확인 된 예외가 마음에 들지 않으면 C#으로 전환하십시오. –

관련 문제