2014-12-01 4 views
6

내가 다음 코드를 얻을 이름 충돌 오류 이해하려고 노력 중이 야의 방법 오버라이드 (override) 할 때 :이름 충돌 제네릭 클래스

import java.util.*; 
import javax.swing.*; 

class Foo<R extends Number> { 
    public void doSomething(Number n, Map<String, JComponent> comps) { 
    } 
} 

class Bar extends Foo { 
    public void doSomething(Number n, Map<String, JComponent> comps) { 
    } 
} 

오류 메시지 :

error: name clash: doSomething(Number,Map<String,JComponent>) in Bar and doSomething(Number,Map<String,JComponent>) in Foo have the same erasure, yet neither overrides the other

내가 해결할 수 알을 그것은 Foo에서 제네릭 형식을 제거하거나 Bar 선언을 class Bar extends Foo<Integer>으로 변경하면됩니다. 내가 알고 싶은 것은이 오류가 특정 경우에 발생하는 이유이지만 각 방법에서 comps 매개 변수를 제거하면 사라집니다. 나는 type erasure에 대해 약간의 독서를 해왔지만 두 가지 방법 모두 제네릭의 유무와 상관없이 동일한 삭제가 있어야하며 따라서 두 경우 모두에서 유효한 무시가되어야합니다. (나는 어디에서나 generic 파라미터를 사용하지 않았다. 그래서 놀랍다.)

나는 부모 클래스에 제네릭 타입을 추가했음을 알고 있지만, 서브 클래스에 대한 경고 만 받았다. 오류가 아닙니다. 누구든지이 시나리오를 설명 할 수 있습니까?

+1

: 당신이 @Override에 확인 할 수있는 적절한 재정,

public void doSomething(Number n, Map comps) { } 

추가 읽기입니다. –

+1

@LuiggiMendoza 그렇습니다. 자바가 generic 매개 변수를 사용하지 않을 때 Java가 이러한 방식으로 다른 지우개를 사용한다고 생각하는 이유는 무엇입니까? 그리고 두 가지 모두에서 'comps' 인수를 제거하면 왜 행복합니까? 아마도 [브리지 메소드] (http://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html)와 관련이 있지만 볼 수는 없습니다. –

+0

'Map' 인터페이스는 제네릭을 사용합니다. 아마도 그것이 불평하는 이유 일 수 있습니다. 어떤 Java 버전을 사용하고 있습니까? 구체적으로 말하자면, 예를 들어 Java 6 u30 또는 Java 7 u40을 의미합니다. –

답변

6

Luiggi is right in the comments. 이것은 raw types의 결과입니다.

The supertype of a class may be a raw type. Member accesses for the class are treated as normal, and member accesses for the supertype are treated as for raw types. In the constructor of the class, calls to super are treated as method calls on a raw type.

이 사항은 수퍼 유형 메소드를 호출 할 때 적용되지만, 또한이를 대체 할 때 적용됩니다. 예를 들어

테이크, 당신이 HashMap<Number, String>Map<String, JComponent>에 할당 할 수있는 타입이 아닌 경우에도, 그것은 컴파일 것을 알 수 있습니다

class Bar extends Foo { 
    public Bar() { 
     doSomething(1, new HashMap<Number, String>()); 
    } 
} 

를 다음과 같습니다.

The type of a constructor (§8.8), instance method (§8.4, §9.4), or non-static field (§8.3) of a raw type C that is not inherited from its superclasses or superinterfaces is the raw type that corresponds to the erasure of its type in the generic declaration corresponding to C .

을 (. 우리의 경우 그 CBar 참고) 그리고 메소드를 오버라이드 (override) 할 때 같은 일이 발생합니다. Foo#doSomething(..) 메소드를 오버라이드 (override)하려고 할 때, 당신의 Bar 클래스는 실제로보고있다가 즉

public void doSomething(Number n, Map comps) { 
} 

로 선언, 형식 매개 변수의 모든 사용은 삭제됩니다. 그래서 하위 Bar의 방법을

public void doSomething(Number n, Map<String, JComponent> comps) { 
} 

를 선언하려고 실제로하지 과부하를 오버라이드 (override)에서 시도이다. 그리고 이것은 유형 삭제 때문에 실패합니다. 당신은 원시`Foo`을 확장하고

+0

특히 오버로딩과 오버라이드에 대한 훌륭한 설명. (실마리가 오류 메시지에 있었지만, 나는 놀랐다.) 당신의 설명을 아래로 분류하기 위해, 하위 클래스가 클래스 수준의 일반 매개 변수를 지정하지 못하면 부모 클래스의 전혀 관련없는 일반 매개 변수도 효과적으로 하위 클래스의 관점에서 사라지다. –

+0

@brad'static' 메소드의 일반적인 사용을 제외한 모든 것. –