2016-10-05 5 views
8

Я пытался сконденсировать эту проблему до наименьшего количества кода, который мог бы.Проблема с параметрами типа Java для возвращаемых значений

Я определил структуру таблицы, как таблицу базы данных, с нижеприведенными ниже классами и Table. A Table по существу является списком . Я хочу, чтобы подклассы определяли их особый вкус Table и , и я хочу, чтобы компилятор поймал неуместные попытки поместить строки одного типа в таблицы несовместимого типа.

Класс Agent предоставляет метод для ввода параметров и возвращает таблицу, которая принимает строки типа T. Для иллюстрации проблемы, которую я имею, я определил три метода.

В FinalAgent, FinalTable и FinalRow классов определяют реализации Agent, Table и классов. В конечном счете, я хочу, чтобы 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; 
    } 
} 

В нижней части:

  • method1 из FinalAgent компилируется, но я должен написать Table<FinalRow> t1 = new FinalAgent().method1(null); для того, чтобы вызвать метод.
  • method2a из FinalAgent я изменил тип возврата к FinalTable, чтобы отразить то, что я на самом деле возвращения (Я хочу написать FinalTable t2a = new FinalAgent().method2a(null);), но компилятор выдает ошибку: Метод method2a (Список) типа FinalAgent необходимо переопределить или реализовать супертип
  • method3 Я изменил параметр от List до String. Метод компилируется нормально, но дает мне предупреждение о безопасности типа, с которым я, по крайней мере, могу работать.

Итак, наконец, вопрос: Является ли это ошибка компилятора, который method2a в FinalAgent ещё 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: нет вопроса (за исключением предупреждения безопасности, хотя, из-за неконтролируемого преобразования)
  • method2a не больше общий метод, но не отменяет что-либо

method2a видно объявлен как это от FinalAgent, после компиляции:

public Table method2a(List parameter) 

Но определяется как это в FinalAgent:

public FinalTable method2a(List<String> parameter) 

И теперь вы застряли. То же стиранием, но не отменяет правильно method2a

Вот простой пример:

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

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

Это дает 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) 
    { 
    } 
} 

Это дает 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

Другой пример. Этот код компилируется нормально:

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

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

Это один не делает:

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

Как только bar становится шаблонным методом, это видно с сырыми типами и мы можем заметить, та же проблема.

Другой пример сырья выпуска тип: Name clash when overriding method of generic class

+0

Где есть сырой тип? Почему происходит беспрепятственное обращение? – shmosel

+0

'method2a' отображается с сырым типом в' Agent', потому что это общий метод с общим типом T – ToYonos

+0

Непроверенное преобразование происходит из 'FinalTable'. Компилятор не может подтвердить, что это ' Таблица ' in 'method2b' – ToYonos

Смежные вопросы