2015-03-02 6 views
0

Почему преобразование из коллекции целых чисел в коллекцию String работает, но это не удается, когда я действительно должен преобразовать Integer в String? Зачем допустить его неудачу/уловить его раньше? В моем примере нижеПреобразование Java Целое число в несогласованность строк

static <T extends List<?> > 
    void testConversion(T... args) 
    { 
     **// Didnt catch here?** 
     List<String>[] slarray = (List<String>[])args; 
     System.out.printf("Value is %s\n", slarray[0].get(0)); 
     **// Didnt catch here?** 
     List<String> slist = (List<String>)args[0]; 
     // FAIL runtime exception 
     String s2 = slist.get(0); 
     // FAIL exception 
     String s = slarray[0].get(0); 
    } 

public static void main(String[] args) 
    { 
     testConversion(Arrays.asList(11,12), Arrays.asList(21,22)); 
    } 
+4

Потому что вы не делаете никакого преобразования там. Просто делаю небезопасный тип ссылок. –

ответ

2

Это потому, что Java Дженерики время компиляции вещь, а фактический тип стирается при запуске программы.

Вы определили свой T как «Список чего угодно». Затем вы передаете ссылку на «Список любых» в «Список строк». Возможно, что этот тип cast будет работать (таким образом, это не ошибка времени компиляции), и поэтому компилятор не жалуется, но оставляет проблему во временной системе.

Во время выполнения это всего лишь ссылка на List. Таким образом, среда времени выполнения также не жалуется: вы создаете массив из List и присваиваете его массиву List, а фактический тип стирается в этот момент.

Но когда дело доходит до получения фактических значений, среда времени выполнения может видеть, что значение фактически не может быть привязано к String, и поэтому оно генерирует исключение.

+0

Я знал часть компиляции. Но во время выполнения это не список всех. Я получаю это сейчас, потому что он просто слепо назначает ссылку. Благодарю. – excalibur

1

Когда вы предоставляете бросание в вашем коде, вы сообщаете компилятору, «Я знаю, у вас есть экземпляр х, но я знаю, что это на самом деле у. Рассматривайте это как у.» Если бросок возможен вообще, то компилятор разрешит его.

Сообщайте компилятору, что args, который он знает, является T[], может быть отлит до List<String>[]. Вы также сообщаете компилятору, что args[0], который он принимает как T, является List<String>.

Это происходит, когда вы звоните testConversion, вы проходите мимо List<Integer> s. Предполагается, что тип T должен быть Integer. Однако из-за стирания стилей во время выполнения они действительно являются List s. Кроме того, литые до List<String>[] и List<String> преуспевают, потому что во время выполнения они действительно отлиты до List[] и List соответственно.

Когда вы скомпилировали, вы должны были получить предупреждение о немедленном предупреждении о литье до List<String>[] и до List<String>. Это предупреждало вас о безопасности типов. Он также вставил бросок на String по вызову get, потому что вы сказали, что это List<String>. Когда вы, наконец, попытались получить String вне вашего List<String>, JVM выбрала исключение для выполнения, потому что элемент действительно был Integer.

Когда вы отлиты args к List<String>[], и когда вы отлиты args[0] к List<String>, вы лгали компилятор, но JVM поймал вашу ложь.