2016-08-16 2 views
0

클래스 B를 확장하지 않으면 출력이 "1233"이지만 클래스 A를 사용하여 클래스 B를 확장하는 것이 컴파일되지 않는 이유는 무엇입니까?java 및 generics의 상속

public class SomeClass { 

    public static class A { 

     public void f(int x){ 
      System.out.print("1"); 
     } 

     public void f(Object x){ 
      System.out.print("2"); 
     } 
    } 

    public static class B // extends A { 

     public <T> void f(T x){ 
      System.out.print("3"); 
     } 
    } 

    public static void main(String[] args){ 
     A a=new A(); 
     B b=new B(); 
     a.f(3); 
     a.f("hello"); 
     b.f(3); 
     b.f("hello"); 
    } 
} 
+2

오류 메시지에 표시되는 내용은 무엇입니까? –

답변

1

유형 삭제 문제로 인해 위의 클래스를 컴파일 할 수 없습니다.

기본 클래스에있는 메서드는 generic이며 부모 클래스의 f(Object x)과 일치합니다. 이것은 컴파일시 발생합니다.

public void f(Object x){} 
public <T> void f(T x){} 

유형 지우기에 대해서는 this Oracle documentation을 참조하십시오.


그러나 int 방법을 유지할 수 있으며, 그것을 잘 컴파일 : 인수 목록이 오버라이드 (override) 된 메소드의 그것과 정확히 같은 경우

class A { 
     public void f(int x){ 
     System.out.print("1"); 
     } 
} 

public class B extends A 
{ 
     public <T> void f(T x){ 
     System.out.print("3"); 
     } 
} 
+1

사실이 아닙니다. 'f (int x)'메서드를 삭제하면 컴파일되지 않습니다. – Codebender

0

방법에만 파생 클래스에서 재정의 할 수 있습니다 반환 유형은 부모 클래스에서 재정의 된 메소드의 반환 유형과 동일하거나 하위 유형이어야합니다.

당신은 SomeClass에서 B 형에 대한 모호한 당신은 Overriding and Hiding Methods

0

때문에 메소드 F (문자열)의 문제에 대한 자세한 정보를 찾을 수 있습니다

public <T> void f(T x) { 
      System.out.print("3"); 
     } 

방법에 따라 재정의 할 수 있습니다, 당신은 그것을 해결할 수 like

public class SomeClass { 
    public static class A { 
     public void f(int x) { 
      System.out.print("1"); 
     } 

     public void f(Object x) { 
      System.out.print("2"); 
     } 
    } 

    public static class B extends A { 
     public void f(Object x) { 
      System.out.print("3"); 
     } 
    } 

    public static void main(String[] args) { 
     A a = new A(); 
     B b = new B(); 
     a.f(3); 
     a.f("hello"); 
     b.f(3); 
     b.f("hello"); 
    } 
} 

그리고 도움이 되길 바랍니다.

3

메서드 서명은 이름 충돌이 발생합니다. 두 메서드 서명은 일반 메서드가 실제로 이전 메서드를 재정의하지 않으므로 이름 충돌이라는 문제가 있습니다. type erasure 이후에는 모두 동일한 서명이 적용됩니다. 방법은 경우에 오버라이드 (override) 할 수 있다고로 B에서 선언

public <T> void f(T x){...} 
public void f(Object x){...} 

메소드

JLS 8.4.8.1. Overriding (by Instance Methods)

, C는 선언 인스턴스 메소드 m을 A 방법을 무시하지 않거나 C 클래스에 의해 상속 받음, C에서 다른 메서드 m A 클래스에서 선언 된 다음의 경우 모두,에 해당합니다

  • A가
  • C는 m에게을 상속하지 않습니다 C.
  • 의 슈퍼 클래스입니다.
  • m C의 서명은 m A의 서명의 서브 서명 (§8.4.2)입니다.
    ....여기에 다음

public static class A { 

    public <T> void f(T x) { 
     System.out.print("3"); 
    } 
} 

public static class B extends A { 

    @Override 
    public void f(Object x) { 
     System.out.print("2"); 
    } 

} 
+0

올바른 방법 : generic 메서드로 메서드를 재정의 할 수 없습니다 (즉, 부모는 generic 일 수 있지만 자식은 아닙니다). – tami

+0

@ tami 정확하지 않습니다. 기본 메소드와 동일한 서명도 유효하며 일부 다른 서명은 일반 메소드의 경우에도 유효합니다. –

+1

"기본 메서드와 동일한 서명도 유효합니다."라는 말은 두 클래스 (A와 B)에서 "public void f (T x)"를 쓰면 올바른 것입니까? "public void f (int x)"("public void f (Object x)"뿐만 아니라)을 넣으면 재정의 할 수 있습니까? – tami

1

자바 제네릭 타입의 삭제를 사용, 유효하고 잘 컴파일합니다.

public <T> void f(T x); 
public void f(Object x); 

모두 javac을 컴파일러에 대한 동일 해결 중에 javac는 충돌이있을 것이다.

다른 example 추가 :

class Test{ 
    void add(Set<Integer> ii){} 
    void add(Set<String> ss){} 
} 

This limitation is part of the language syntax, not the Java runtime itself. Essentially, this rule is intended to avoid conflicts in legacy code that still uses raw types.

위의 답변을 참조하시기 바랍니다.