2014-09-02 2 views
0

Недавно я закончил курс онлайн в AP Computer Science (Java) и на выпускном экзамене был вопрос, что-то вроде этого:Java Неопределенное Generics Кронштейны Использование

Which of these needs a String cast to use String methods on it:
I. ArrayList a = new ArrayList();
II. ArrayList<Object> b = new ArrayList<Object>();
III. ArrayList<String> c = new ArrayList<String>();

Что-то об этом спутать меня: может Опция I когда-нибудь сможет быть отлита? У этого нет никакого общего определения, так что, если компилятор Java не предопределен ArrayList<Object>, то какой класс E?


Это мой тестовый код (Подавить комментарии необходимы, потому что это «непроверенный» операция):

ArrayList a = new ArrayList(); 

@SuppressWarnings("unchecked") 
a.add(new Object()); 

@SuppressWarnings("unchecked") 
a.add(new String("test")); 

@SuppressWarnings("unchecked") 
a.add(null); 

System.out.println((String)(a.get(0))); 

Независимо от того, что в аргументах для метода add(), он всегда дает ошибка компилятора:

test.java:14: error: <identifier> expected 
     a.add(new Object()); 
      ^

Если я пытаюсь добавить идентификатор в любом месте кода (например: a<Object>.add(new Object())) дает точно такую ​​же ошибку, как и раньше.

Вопрос в том, что на самом деле происходит, когда параметр не передается параметру generics и может ли что-либо быть добавлено в этот список в первую очередь, не говоря уже о том, чтобы бросить в другой объект? Заранее спасибо!

+0

«Идентификатор ожидается» означает «синтаксическая ошибка». Я не думаю, что это имеет ничего общего с дженериками. Я не вижу ничего плохого в коде, который у вас есть. Пожалуйста, дважды проверьте его, и через секунду у меня будет IDE. – markspace

+0

@markspace Я дважды проверил его. Я предполагаю, что ему нужен объект типа E (или, по крайней мере, подкласс E), и он не находит его. – portablesounds

ответ

1

У вас простая синтаксическая ошибка. @SuppressWarnings не может использоваться в таких инструкциях, как a.add(x), только объявления классов, декларации методов и объявления переменных. Вот почему он запрашивает идентификатор, @SuppressWarnings ожидает увидеть один из этих трех, а не простой оператор.

public static void main(String[] args) { 
     ArrayList a = new ArrayList(); 
     a.add(new Object()); 
     a.add(new String("test"); 
     a.add(null); 
     System.out.println((String) (a.get(0))); 
    } 

Код компилируется точно так.

Итак, что происходит, когда вы используете сырой тип? Ничего. Проверка типов не производится. Вышеприведенный код создает java.lang.ClassCastException error в инструкции println. Не поймать, что вы положили Object, когда вы хотели поставить String, и он не знает до тех пор, пока вы не нажмете на println.

+0

Спасибо! Вот что было! Угадайте, что они были правы: / – portablesounds

0

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

Это означает, что:

List lst = new ArrayList(); 

полностью эквивалентно:

List<Object> lst = new ArrayList<Object>(); 

В таком списке, все могут быть добавлены или извлечены, потому что все в Java расширяет объект, за исключением примитивов (но то вступает в действие автобоксинг).

Таким образом, вы можете правильно написать:

lst.add("String"); 
lst.add(new Date()); 
lst.add(new Integer(1)); 
lst.add(1); // It is converted to an Integer by auto-boxing 

И вы можете правильно написать:

String str = (String)lst.get(0); 

Но вы должны быть осведомлены о возможных исключений во время выполнения броска:

String str2 = (String)lst.get(1); // Will give error, cause element 1 is a date. 

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

public class MyList<E extends MyClass> extends ArrayList<E> { 

вы все еще можете использовать его без дженериков:

MyList lst = new MyList(); 

Но он будет принимать только MyClass или подклассы MyClass:

lst.add(new MyClass()); 
lst.add(new MySubClass()); 
MyClass a = lst.get(0); 
MyClass b = lst.get(1); 
MySubClass c = (MySubClass)lst.get(1); 

Но ничто иное:

lst.add("String"); // Will give compile time error 
+0

Хммм, почему же не компиляция кода, хотя я не могу найти что-то неправильно с синтаксисом? Также, если это правда, мне также не придется подавлять «непроверенную» ошибку. – portablesounds

+0

@markspace ответил на вопрос, почему он не компилировался, пока я писал полное объяснение :) –

+0

unchecked не является ошибкой, это просто предупреждение, которое компилятор дает вам знать, что вы используете параметризованный класс без использования параметров generics. –

Смежные вопросы