Я пишу для себя руководство по java, и мне нравится добавлять в него твердые факты. Кажется, я не могу описать параметр универсального типа. Мне интересно, какое имя отображается как общий тип для компилятора, а не как существующий объект. Я знаю, что это буква «Т» и другие отдельные буквы. Но я видел на oracle.docs.com пример вроде:
class name<T1, T2, ..., Tn>{}
Так что теперь я запутался. Чтобы компилятор принял имя в качестве параметра универсального типа, не должно ли существовать только класса с таким именем? Если бы у меня был класс Боби:
class Boby{ ... }
Затем, если я создам метод и неправильно введу имя класса Бобу:
void Method(Bob parameter){}
Будет ли это просто компилироваться, а параметр должен быть универсальным типом?
Почему бы тебе просто не проверить это? Чтобы метод был универсальным, он должен декларировать, что он имеет по крайней мере один универсальный тип. И почему вы не уважаете соглашения об именах? Это должно быть в самом начале вашего руководства, задолго до дженериков.
Вы можете взглянуть на JLS (спецификацию языка Java), которая определяет общие параметры и то, как обрабатываются конфликты имен. Как правило, универсальный параметр должен быть объявлен в <...> и IIRC, он имеет приоритет над именами классов - поэтому общие типы обычно называются T, V, T2 и т. д. - потому что классы обычно имеют более длинные и значимые имена.




Любое имя может быть параметром универсального типа. Если вы объявляете параметр универсального типа 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
Параметр типа, объявленный в классе, затеняет любой фактический класс, как это сделал бы локальный класс:
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;
<T1>объявляетT1как универсальный параметр (переменная типа в спецификации языка Java), еслиBobне объявлен как таковой, он не будет интерпретирован как один (похожий для объявления переменной). Пример<Bob> void method(Bob parameter)