Следующий код не компилируется:
public class GenericsTest {
public static void main(String[] args) {
MyList<?> list = new MyList<Object>();
Class<?> clazz = list.get(0);
// Does not compile with reason
// "Type mismatch: cannot convert from Object to Class"
MyList list2 = new MyList();
Class clazz2 = list2.get(0);
}
static class MyList<T> extends ArrayList<Class<T>> {
}
}
Я хотел сделать это, чтобы внедрить дженерики в старый код без нарушения сборки.
Это ошибка как компилятора (как eclipse, так и javac), или мне что-то здесь не хватает? Какая еще возможность существует для введения дженериков в MyList?
РЕДАКТИРОВАТЬ
В целях разъяснения:
У меня есть общий класс
public class MyList extends ArrayList<MyObject> {}
с
public class MyObject {}
и код с использованием MyList
MyList list = new MyList();
...
MyObject o = list.get(0);
Теперь, во время разработки, я вижу, что хочу добавить дженерики в MyObject.
public class MyObject<T> {}
и теперь я хочу, чтобы эта новая общая штука была в MyList
public class MyList<T> extends ArrayList<MyObject<T>> {}
Но это ломает мою сборку. интересно
public class MyList<T> extends ArrayList<MyObject<T>> {
public MyObject<T> get(int i) {
return super.get(i);
}
}
позволит старый код
MyList list = new MyList();
...
MyObject o = list.get(0);
компилировать.
Хорошо, кажется, что когда я представлю этот общий, мне придется смириться с необходимостью изменить все вызовы MyList на универсальную форму. Я хотел, чтобы старый код просто выводил предупреждение вместо ошибки.
Ошибка компиляции находится в комментарии к образцу.




Ты пробовала:
Class clazz2 = list2.get(0).getClass();
Об этом читайте здесь: http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#getClass ()
Но это не то же самое! String.class! = String.class.getClass ()
Я думаю, вы не совсем понимаете, как работают дженерики.
MyList<?> list = new MyList<Object>();
Class<String> clazz= list.get(0);
Этот фрагмент кода не компилируется, потому что вы сообщаете компилятору, что list будет содержать типы Class<Object>, а затем в следующей строке вы ожидаете, что он вернет вам Class<String>. Универсальная система в Java не способна преобразовывать типы, используемые с универсальными шаблонами, на основе наследования, как вы могли бы подумать.
Если вы ожидаете, что list будет содержать Class<String>, вам нужно объявить его так, или, если вы хотите, чтобы он мог содержать любые типы, вы не можете выполнить вторую строку без приведения.
MyList<String> list = new MyList<String>();
Class<String> clazz = list.get(0);
или же
MyList<?> list = new MyList<Object>();
//generates a warning about an unchecked cast
Class<String> clazz = (Class<String>) list.get(0);
Второй фрагмент кода не работает, потому что, когда вы используете необработанные типы, вам все равно нужно привести Object, возвращаемый get(), к объявленному типу, который вы используете (что всегда имело место).
MyList list2 = new MyList();
Class clazz2 = (Class) list2.get(0);
Я думаю, вы не видели объявление класса MyList в конце: статический класс MyList <T> расширяет ArrayList <Class <T>>. Определено, что MyList <T> принимает Class <T> -Objects.
Верно, я уловил это в конце, но он ожидает, что MyList <Object> будет преобразован в MyList <String>, а это не так.
Нет, я не ожидаю, что MyList <Object> можно будет преобразовать в MyList <String>. Я хочу, чтобы MyList можно было преобразовать в MyList <?>. Извините, в моем примере произошла ошибка.
Что ж, с вашим исправленным примером мой второй ответ все еще применим - метод get () в необработанном списке возвращает объект, поэтому вам нужно явно привести его к классу.
У меня нет компилятора на этой машине, но он должен работать.
public class GenericsTest {
public static void main(String[] args) {
MyList<Object> list = new MyList<Object>();
Class<?> clazz= list.get(0);
}
static class MyList<T> extends ArrayList<Class<? extends T>> {
}
}
Да, это так. Существует ошибка времени выполнения, поскольку он вызывает get () в пустом списке, но код компилируется.
Да, ваш код компилируется, но не "Class clazz = list.get (0);" ни "MyList <String> list = new MyList <String> (); Class <String> clazz = list.get (0);". «Класс <? Extends String> clazz = list.get (0);» будет работать, но не по назначению.
В вашем примере MyList - это старый код, который вы хотите обновить для поддержки дженериков? Если да, то какой тип объектов должен содержать мой список?
Как упоминалось здесь в другом месте, ошибка компиляции действительна. Это связано с тем, что доступ к необработанному списку осуществляется без преобразования get в Class. Следовательно, код пытается назначить объект ссылке на класс. Это эквивалентно этому:
Object o = new Object();
Class c = o;
Которая просто не может скомпилироваться. Кроме того, чтобы в полной мере использовать дженерики, вы должны отдавать предпочтение Class <?> Вместо Class.
В вашем примере второй пример не работает, потому что вы не используете дженерики, поэтому это означает, что метод get () вернет объект, и вам нужно будет преобразовать его в класс. Если вы не указываете тип своего MyList:
MyList list2 = new MyList();
Тогда вы теряете преимущества Generics, и вам нужно приводить объект при вызове метода get (), как в старые добрые времена.
Было бы полезно, если бы вы указали ошибку компиляции, а также код.