Что делает имя параметра универсального типа универсальным?

Я пишу для себя руководство по java, и мне нравится добавлять в него твердые факты. Кажется, я не могу описать параметр универсального типа. Мне интересно, какое имя отображается как общий тип для компилятора, а не как существующий объект. Я знаю, что это буква «Т» и другие отдельные буквы. Но я видел на oracle.docs.com пример вроде:

class name<T1, T2, ..., Tn>{}

Так что теперь я запутался. Чтобы компилятор принял имя в качестве параметра универсального типа, не должно ли существовать только класса с таким именем? Если бы у меня был класс Боби:

class Boby{ ... }

Затем, если я создам метод и неправильно введу имя класса Бобу:

void Method(Bob parameter){}

Будет ли это просто компилироваться, а параметр должен быть универсальным типом?

<T1> объявляет T1 как универсальный параметр (переменная типа в спецификации языка Java), если Bob не объявлен как таковой, он не будет интерпретирован как один (похожий для объявления переменной). Пример <Bob> void method(Bob parameter)
user85421 04.12.2018 13:48

Почему бы тебе просто не проверить это? Чтобы метод был универсальным, он должен декларировать, что он имеет по крайней мере один универсальный тип. И почему вы не уважаете соглашения об именах? Это должно быть в самом начале вашего руководства, задолго до дженериков.

JB Nizet 04.12.2018 13:48
en.wikipedia.org/wiki/Generics_in_Java
SanRyu 04.12.2018 13:48

Вы можете взглянуть на JLS (спецификацию языка Java), которая определяет общие параметры и то, как обрабатываются конфликты имен. Как правило, универсальный параметр должен быть объявлен в <...> и IIRC, он имеет приоритет над именами классов - поэтому общие типы обычно называются T, V, T2 и т. д. - потому что классы обычно имеют более длинные и значимые имена.

Thomas 04.12.2018 13:49
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
4
77
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Любое имя может быть параметром универсального типа. Если вы объявляете параметр универсального типа Bob и используете это имя вместо предполагаемого имени класса Boby, компилятор распознает его как параметр универсального типа.

Кстати, если вы объявляете параметр универсального типа Boby, он скроет имя класса Boby, поэтому запись Boby в любом месте области, где определен этот параметр универсального типа (либо внутри всего класса, либо внутри одного метода), будет относиться к универсальному параметр типа, а не класс Boby.

class Something<Bob> {
    void Method1(Bob parameter){} // refers to the generic type parameter Bob

    void Method2(Boby parameter){} // refers to the Boby class
}

class Something<Boby> {
    void Method(Boby parameter){} // refers to the generic type parameter Boby,
                                  // hiding the Boby class
}

class Something<T> {
    void Method(Bob parameter){} // compilation error - Bob is an undefined symbol
}

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

Хорошее объяснение, спасибо. Я неправильно понял концепцию параметров. Думал, что они могут быть как параметры необъявленного типа где угодно, лол, это было бы сказкой: D

Žan Spehonja 04.12.2018 14:24

Параметр типа, объявленный в классе, затеняет любой фактический класс, как это сделал бы локальный класс:

interface HasValue {
    int getValue();
}
class Foo {
}

class Bar implements HasValue {
    private int value;

    public Bar(int v) {
        this.value = v;
    }
    public int getValue() {
        return this.value;
    }
}

class Example<Foo extends HasValue> {
    public static final void main(String[] args) throws Exception {
        Example<Bar> e = new Example<>();
        e.method(new Bar(42));
    }

    public void method(Foo x) {
        System.out.println("x.getValue() is " + x.getValue());
    }
}

Это прекрасно работает, потому что в ExampleFoo является параметром типа, а не классом Foo.

Чтобы компилятор знал, используется ли класс как универсальный, вам нужно указать его следующим образом:

public class MyClass<T> {}

Например, если вы создаете универсальный список для списка, предположим следующее:

List<Bob> bobyes = new ArrayList<Bob>();

Итак, теперь у вас есть список универсальных шаблонов, содержащих элементы класса типа Bob. Тип каждого элемента в списке - Боб.

Если вы выполните итерацию, у вас будет:

foreach (Bob bob : bobyes)
   if (bob instanceof Bob)
      true; -- in this case always true;

Другие вопросы по теме