2013-12-09 6 views
4

Есть несколько простых классов тест-случай:Java дженериков, объяснение необходимости

public interface ListCriteria<T> { 
    // some stuff here 
} 

public class UserListCriteria implements ListCriteria<User> { 
// implementation 
} 

public interface Editor<T> { 
    // sample method 1 
    List<T> listObjectsTest1(ListCriteria<T> criteria); 
    // sample method 2 
    <L extends ListCriteria<T>> List<T> listObjectsTest2(L criteria); 
} 

И есть реализация Editor которой Java считает, что не обеспечивает необходимую реализацию для обоих образцов методами:

public class UserEditor implements Editor<User> { 

    @Override 
    public List<User> listObjectsTest1(UserListCriteria criteria) { 
    // 
    } 

    @Override 
    public List<User> listObjectsTest2(UserListCriteria criteria) { 
    // 
    } 
} 

Ошибки обоих методов неверны. Вопрос в том, почему. Особенно для последнего метода. Конечно, я мог бы сделать interface Editor<T, L extends ListCriteria<T>>, и это решит проблему, но я не хочу, я хочу понять, почему я не могу использовать дженерики уровня метода здесь.

ответ

2

Ошибки, которые вы получаете, не имеют ничего общего с дженериками, поскольку вы реализуете метод с другим типом, чем применяет интерфейс.

Интерфейс Editor определяет

List<T> listObjectsTest1(ListCriteria<T> criteria); 

Таким образом UserEditor должен реализовать в вашем случае

public List<User> listObjectsTest1(ListCriteria<User> criteria) { 

Вы не должны ошибочно типа параметра с универсальным типом параметра. Интерфейс Editor обеспечивает использование типа ListCriteria. Общий тип ListCriteria составляет T, а T может быть связан подклассом, например implements ListCriteria<User>. Вот что я имею в виду, когда говорю «Ошибки, которые вы получаете, не имеют ничего общего с дженериками».

Я предполагаю, что вы хотели было

public interface Editor<C, T extends ListCriteria<C>> { 
    List<C> listObjectsTest1(T criteria); 
} 

, а затем UserEditor может быть реализован как

public class UserEditor implements Editor<User, UserListCriteria> { 

    public List<User> listObjectsTest1(UserListCriteria criteria) { 
     return null; 
    } 
} 

почему? Специально для последнего метода

Второй метод в интерфейсе Editor

<L extends ListCriteria<T>> List<T> listObjectsTest2(L criteria); 

не означает, что вы можете реализовать любой тип связывания L UserEditor должны еще осуществлять

public <L extends ListCriteria<User>> List<User> listObjectsTest2(L criteria) { 
    return null; 
} 

Этот метод определяет общий тип L, который будет связан, когда clien t вызывает метод. Таким образом, вы можете вызвать метод с любым типом, который является подтипом ListCriteria<User>.

+0

С уважением, могу ли я правильно сказать, что я могу переопределить тип возвращаемого значения, но не аргументы метода, и что я должен придерживаться точно таких же сигнатур arg, даже если 'UserListCriteria' отлично вписывается во время выполнения? – Osw

+0

@ Osw Я обновил ответ и надеюсь, что теперь станет ясно. –

1
  1. Ваша listObjectsTest1(UserListCriteria criteria) функция UserEditor не отменяя функцию listObjectsTest1(ListCriteria<T> criteria) из Editor<T> интерфейса, поскольку они имеют две разные подписи, то есть, по существу, тип аргумента.

  2. То же самое относится и к listObjectsTest2, который был объявлен в интерфейсе: <L extends ListCriteria<T>> List<T> listObjectsTest2(L criteria); но вы объявили его в UserEditor классе, как: List<User> listObjectsTest2(UserListCriteria criteria)

Так что вам нужно будет изменить подпись:

class UserEditor implements Editor<User> { 


    @Override 
    public List<User> listObjectsTest1(ListCriteria<User> criteria) { 

    } 

    @Override 
    public <L extends ListCriteria<User>> List<User> listObjectsTest2(L criteria) { 

    } 
} 

Для получения более подробной информации, пожалуйста, прочитайте jls 8.4.8. Inheritance, Overriding, and Hiding.

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