Расширение общих классов - PullRequest
       13

Расширение общих классов

51 голосов
/ 31 августа 2011
public class MyGeneric<T, E> {}

public class Extend1<T, E> extends MyGeneric<T, E> {}

public class Extend2 extends MyGeneric<String, Object> {}

Насколько мне известно, оба подкласса в приведенном выше примере являются действительными.Мне было интересно, как Java знает, когда типы, заданные в суперклассе, будут определены, когда создается экземпляр подкласса, и когда они являются реальными именами классов (т.е. как он знает, что T, E не являются именами классов)?1003 * Примечание: допустимо ли (даже если оно редко) использовать более одной буквы для универсальных типов?Что если (из-за серьезной ошибки планирования) Типы конфликтуют с существующим классом, например,

public class E{}
public class Foo<E>{}

что происходит потом?

Редактировать: Спасибо за быстрый ответ.Чтобы ответить на мой первый вопрос, ответ Иоахима наиболее эффективен.

Чтобы ответить на дополнительный вопрос, ответ aioobe яснее

Ответы [ 3 ]

58 голосов
/ 31 августа 2011

Давайте посмотрим на это определение:

public class Extend1<T, E> extends MyGeneric<T, E> {}

Здесь T и E каждый присутствует дважды и в двух разных ролях

  • в Extend1<T,E> вы определяете аргументы типа. Это означает, что тип Extend1 имеет два (неограниченных) аргумента типа T и E. Этот сообщает компилятору Java, что те, кто использует Extend1, должны указать типы.
  • в extends MyGeneric<T,E> вы используете ранее определенные аргументы типа. Если бы T и E не были известны как аргументы типа, тогда T и E были бы ссылками на простые типы, т.е. компилятор будет искать классы (или интерфейсы, ...) с именем T и E (и, скорее всего, не найти их).

Да, аргументы типа следуют тем же синтаксическим правилам, что и любой другой идентификатор в Java, поэтому вы можете использовать несколько букв ABC или даже имена, которые могут сбивать с толку (использование аргумента типа с именем String допустимо, но очень запутанно).

Имена аргументов однобуквенного типа - это просто очень распространенная стратегия именования.

22 голосов
/ 31 августа 2011

Мне было интересно, как Java знает, когда типы, заданные в суперклассе, будут определены при создании экземпляра подкласса, и когда они являются фактическими именами классов (т. Е. Откуда он знает, что T, E не имена классов)?

Java не волнует. Если вы делаете ...

class MyGeneric<String> extends ArrayList<String> {
    String value;
}

допустимо (даже если редко) использовать более одной буквы для универсальных типов? Что если (из-за серьезной ошибки планирования) Типы конфликтуют с существующим классом, например

Да, вы можете использовать любой допустимый идентификатор Java для параметров типа.

Имена могут конфликтовать, но Java не будет воспринимать это как ошибку. Идентификаторы между < ... > всегда будут рассматриваться как параметры типа, независимо от того, соответствует ли идентификатор имени класса.

Хотя это может запутать. Вот пример:

class MyGeneric<String> extends java.util.ArrayList<String> {
    String value;
}

class Test {
    public static void main(String... args) throws Exception {
        MyGeneric<Integer> obj = new MyGeneric<Integer>();
        obj.value = 5;
        //          ^
        //          |
        //          '--- Assign an integer to what seems to be a String!
    }
}

Аналогичный вопрос:

2 голосов
/ 31 августа 2011

Нет проблем с:

public class E{}
public class Foo<E>{}

Поскольку в контексте Foo<E>, E является типом.

...