Если вы создаете общий класс в Java (у класса есть общие параметры типа), можете ли вы использовать общие методы (метод принимает общие параметры типа)?Общие методы Java в классах генерических классов
Рассмотрим следующий пример:
public class MyClass {
public <K> K doSomething(K k){
return k;
}
}
public class MyGenericClass<T> {
public <K> K doSomething(K k){
return k;
}
public <K> List<K> makeSingletonList(K k){
return Collections.singletonList(k);
}
}
Как и следовало ожидать, с общим методом, я могу назвать doSomething(K)
о случаях MyClass
с любым объектом:
MyClass clazz = new MyClass();
String string = clazz.doSomething("String");
Integer integer = clazz.doSomething(1);
Однако, если я пытаюсь использование экземпляров MyGenericClass
без с указанием общего типа, Я звоню doSomething(K)
, возвращает Object
, независимо от того, что K
был принят в:
MyGenericClass untyped = new MyGenericClass();
// this doesn't compile - "Incompatible types. Required: String, Found: Object"
String string = untyped.doSomething("String");
Как ни странно, он будет собирать, если возвращаемый тип является общий класс - например, List<K>
(На самом деле, это можно объяснить - см ответ ниже):
MyGenericClass untyped = new MyGenericClass();
List<String> list = untyped.makeSingletonList("String"); // this compiles
Кроме того, он будет компилировать, если общий класс набирается, даже если только символы:
MyGenericClass<?> wildcard = new MyGenericClass();
String string = wildcard.doSomething("String"); // this compiles
ли есть ли веская причина, почему вызов универсального метода в нетипизированном родовом классе не должен работать?
Есть ли какой-нибудь умный трюк, относящийся к общим классам и общим методам, которые мне не хватает?
EDIT:
Чтобы уточнить, я бы ожидать нетипизированная или сырой типизированных общий класс не чтить параметры типа родового класса (потому что они не были предоставлены). Однако мне непонятно, почему нетипизированный или не типичный типичный класс будет означать, что общие методы не соблюдаются.
Понятно, что этот вопрос уже поднят на SO, c.f. this question. Ответы на это объясняют, что, когда класс является нетипизированным/в его исходной форме, все дженериков удаляются из класса, включая типизацию общих методов.
Однако на самом деле нет объяснений, почему это так. Поэтому позвольте мне уточнить мой вопрос:
- Почему Java удаляет общий метод ввода на нетипизированных или нестандартных классах классов? Есть ли веская причина для этого, или это просто надзор?
EDIT - обсуждение JLS:
Было предложено (в ответ на предыдущий SO вопрос и на этот вопрос), что рассматривается в JLS 4.8, в котором говорится:
тип конструктора (§8.8), метод экземпляра (§8.4, п. 9.4) или нестатическое поле (§8.3) М исходного типа С, не унаследованными от своего суперкласса или суперинтерфейсов является исходным типом, который соответствует стиранию его типа в родовой декларации, соответствующие C.
Это ясно мне, как это относится к нетипизированному классу - типовые типы класса заменяются типами стирания. Если обобщенные обобщенные классы связаны, то тип стирания соответствует этим границам. Если они не связаны, то тип стирания является объектом - например.
// unbound class types
public class MyGenericClass<T> {
public T doSomething(T t) { return t; }
}
MyGenericClass untyped = new MyGenericClass();
Object t = untyped.doSomething("String");
// bound class types
public class MyBoundedGenericClass<T extends Number> {
public T doSomething(T t) { return t; }
}
MyBoundedGenericClass bounded = new MyBoundedGenericClass();
Object t1 = bounded.doSomething("String"); // does not compile
Number t2 = bounded.doSomething(1); // does compile
Хотя общие методы являются методами, например, не ясно мне, что JLS 4.8 относится к общим методам. Тип обобщенного метода (<K>
в более раннем примере) не является нетипизированным, так как его тип определяется параметрами метода - только класс является нетипизированным/необработанным.
Возможный дубликат [Объединение сырых типов и общих методов] (http://stackoverflow.com/questions/11007723/combining-raw-types-and-generic-methods). См. Также: [Почему этот общий код Java не компилируется?] (Http://stackoverflow.com/questions/662191/why-wont-this-generic-java-code-compile) –
http://stackoverflow.com/questions/14882003/generic-screw-up-non-related-collection/14882590 # 14882590 :) – Affe
@PaulBellora - спасибо.Первое очень сильно связано - хотя мой обильный поиск SO не нашел его, поэтому спасибо за ссылку. Второе менее актуально, поскольку оно охватывает только общие классы - не общие методы. – amaidment