2016-10-05 2 views
8

가능한 한 적은 코드로이 문제를 해결하려고했습니다.반환 값에 Java 형식 매개 변수가있는 문제

아래와 같이 및 Table 클래스가있는 데이터베이스 테이블과 같은 테이블 구조를 정의했습니다. Table은 본질적으로 의 목록입니다. 서브 클래스가 Table과 의 특정 풍미를 정의하고 컴파일러가 한 유형의 행을 호환되지 않는 유형의 테이블에 넣으려는 부적절한 시도를 포착하기를 원합니다.

추상화 Agent 클래스는 매개 변수를 취하고 T 유형의 행을 사용하는 테이블을 반환하는 메소드를 제공합니다. 나는 내가 가지고있는 문제를 설명하기 위해 세 가지 방법을 정의했다.

FinalAgent, FinalTableFinalRow 클래스는 Agent, TableRow 클래스 구현을 정의한다. 궁극적으로, 내가 원하는 것은 method2a이며, 이는 매개 변수 목록을 받아 FinalTable 유형의 테이블을 반환합니다.

public abstract class Row {} 
public abstract class Table<T extends Row> {} 
public abstract class Agent { 
    public <T extends Row> Table<T> method1(List<String> parameter) { 
     return null; 
    } 
    public <T extends Row> Table<T> method2a(List<String> parameter) { 
     return null; 
    } 
    public <T extends Row> Table<T> method2b(String parameter) { 
     return null; 
    } 
} 

public class FinalRow extends Row {} 
public class FinalTable extends Table<FinalRow> {} 
public class FinalAgent extends Agent { 
    @Override 
    public <T extends Row> Table<T> method1(List<String> parameter) { 
     return null; 
    } 
    @Override 
    public FinalTable method2a(List<String> parameter) { 
     return null; 
    } 
    @Override 
    public FinalTable method2b(String parameter) { 
     return null; 
    } 
} 
하단에서

: FinalAgent 컴파일의

  • method1,하지만 난 메소드를 호출하기 위해 Table<FinalRow> t1 = new FinalAgent().method1(null);를 작성해야합니다. FinalAgent
  • method2a 나는 내가 실제로 (내가 FinalTable t2a = new FinalAgent().method2a(null);를 작성하려는) 반환하고 무엇을 반영하기 위해 FinalTable에 반환 형식을 변경하지만, 컴파일러는 오류 발생 : 유형의 FinalAgent의 방법 method2a (목록) 오버라이드 (override) 또는를 구현해야합니다 슈퍼 유형 메소드
  • method3 매개 변수를 List에서 String으로 변경했습니다. 메서드는 OK를 컴파일하지만 나에게 적어도 작업 할 수있는 형식 안전 경고를줍니다.

그래서, 결국, 문제는 : 그것은 FinalAgentmethod2a 아직 method2b 컴파일되지 않습니다 만, 이것은 컴파일러의 버그가 컴파일 않습니다 있습니까?

나는 또한 물을 수도 있습니다, 내가하고있는 일을하는 더 좋은 방법이 있습니까?

+0

@ElliottFrisch? – shmosel

+0

@shmosel 실수로, FinalTable 선언에서 제네릭 타입을 놓쳤습니다. –

+0

궁금한 불일치입니다. – shmosel

답변

8

왜 메서드를 매개 변수화하는지 명확하지 않습니다. Table<T>을 반환 하겠지만 시간 소거 유형으로 인해 메소드가 T을 런타임에 식별 할 수 없습니다. 당신은 아마 대신 전체 Agent 클래스를 매개 변수화 할 :

public abstract class Agent<T extends Table<?>> { 
    public T method1(List<String> parameter) { 
     return null; 
    } 
    public T method2a(List<String> parameter) { 
     return null; 
    } 
    public T method2b(String parameter) { 
     return null; 
    } 
} 

public class FinalAgent extends Agent<FinalTable> { 
    @Override 
    public FinalTable method1(List<String> parameter) { 
     return null; 
    } 
    @Override 
    public FinalTable method2a(List<String> parameter) { 
     return null; 
    } 
    @Override 
    public FinalTable method2b(String parameter) { 
     return null; 
    } 
} 

초기 질문에 관해서는, 내가 불일치 또는 method2b에 경고 메시지를 이해 할 수 없습니다.하나의 장소에있어서의 파라미터를 사용

1

파라미터 일반적 Agent에서 같은 방법에

불필요 수단 FinalAgent 잘 컴파일이 원시 형태의 직접적인 결과이다

public Table<? extends Row> method2a(List<String> parameter) { 
    return null; 
} 
public Table<? extends Row> method2b(String parameter) { 
    return null; 
} 
1

.

  • method1은 여전히 ​​일반적인 방법입니다. 문제는 없습니다.
  • method2b 더 이상 일반적인 방법이 아니라 Agent의 방법 오버라이드 (override) :
  • method2a 더 이상 일반적인 방법은 아닙니다 (때문에 선택하지 않은 변환, 비록 안전 경고 제외) 아무 문제가 있지만 아무것도에게
  • 무시하지 않습니다

method2a은 컴파일 후, FinalAgent에서 다음과 같이 선언 볼 수 있습니다 :

public Table method2a(List parameter) 
public FinalTable method2a(List<String> parameter) 

을 그리고 지금 당신은 붙어 있습니다그러나 FinalAgent에 다음과 같이 정의했다.

public interface Foo 
{ 
    public void bar(List a); 
} 

public class FooChild implements Foo 
{ 
    @Override 
    public void bar(List<String> a) 
    { 
    } 
} 

그것은 그것은 Name clash: The method bar(List<String>) of type FooChild has the same erasure as bar(List) of type Foo but does not override it

또 다른 예를 제공 The method bar(List<String>) of type FooChild must override or implement a supertype method

public interface Foo 
{ 
    public void bar(List a); 
} 

public class FooChild implements Foo 
{ 
    public void bar(List<String> a) 
    { 
    } 
} 

제공 : 동일 삭제하지만, 여기에 제대로 method2a

을 무시하지 않는 간단한 예입니다. 이 코드는 잘 컴파일 :

public interface Foo 
{ 
    public void bar(List<String> a); 
} 

public class FooChild implements Foo 
{ 
    public void bar(List<String> a) 
    { 
    } 
} 

을이 하나가되지 않습니다 그것은 원시 유형으로 볼 수, bar는 일반적인 방법됨에 따라

public interface Foo 
{ 
    public <T> void bar(List<String> a); 
} 

public class FooChild implements Foo 
{ 
    public void bar(List<String> a) 
    { 
    } 
} 

그것은 곧 Name clash: The method bar(List<String>) of type FooChild has the same erasure as bar(List<String>) of type Foo but does not override it

를 제공하고 우리가 알 수 있습니다 같은 문제.

원시 형 문제의 다른 예 : 원시 유형의 Name clash when overriding method of generic class

+0

원시 형식은 어디에 있습니까? 검사되지 않은 전환이있는 이유는 무엇입니까? – shmosel

+0

'method2a'는'Agent'에서 원시 타입으로 볼 수 있습니다. 일반 타입 T를 가진 제네릭 메소드 T – ToYonos

+0

체크되지 않은 변환은'FinalTable'에서옵니다. 컴파일러는'method2b'에서' Table '을 확인할 수 없습니다. – ToYonos

관련 문제