Подтвердить что ты не робот

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

public class MyGeneric<T, E> {}

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

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

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

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

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

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

Изменить: Спасибо, что ответили так быстро. Чтобы ответить на мой первый вопрос, Ответ Joachim является наиболее эффективным.

Чтобы ответить на боковую точку, ответ на aioobe более ясный

4b9b3361

Ответ 1

Посмотрите на это определение:

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 является законным, но высокий запутанный).

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

Ответ 2

Мне было интересно, как 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!
    }
}

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

Ответ 3

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

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

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