Подтвердить что ты не робот

Generics List <String> и List <Integer> не ведут себя как ожидалось

Почему println печатает "tom" и не показывает какое-либо исключение во время выполнения после каста на List<Integer>, в то время как он не может напечатать значение 1 после кастинга до List<String>?

import java.util.Arrays;
import java.util.List;

public class Main {
    public static void main(String args[]) {

        List list = Arrays.asList(1, "tom");

        System.out.println(((List<Integer>) list).get(1));
        // "tom"

        System.out.println(((List<String>) list).get(0));
        // ClassCastException: Integer cannot be cast to String
    }
}
4b9b3361

Ответ 1

Первый вызов println статически отправляется на PrintStream.println(Object), а второй вызов отправляется на PrintStream.println(String). Таким образом, для второго вызова компилятор помещает неявный приведение в String, который затем не работает с ClassCastException во время выполнения.

Ответ 2

Проблема заключается в том, что компилятор java выбирает методы во время компиляции, а не во время выполнения. И во время компиляции он выберет метод PrintStream.print(String), а не PrintStream.print(int) или PrintStream.print(Object), оба из которых будут успешными.

Ответ 3

Integer i = new Integer(101);
String s = new String(i); // undefined and Invalid
StringBuffer sb = new StringBuffer(i); // defined and Valid

String s2 = "tom";
Integer i2 = new Integer(s2); //defined and valid

Поэтому, когда вы назначаете не общий список для общего, он присваивается, но когда вы его печатаете, он проверяет безопасность типа или определяет конструкторы для кастинга, если есть допустимые и определенные конструкторы, тогда он напечатан, иначе показывает исключение класса cast поскольку класс не может быть издан из-за отсутствия конструкторов undefined для кастинга.

Если я ошибаюсь, помогите мне с правильной логикой...

Ответ 4

Эта проблема может быть устранена с помощью дженериков и является основной мотивацией использования дженериков.

Это фактический поток вашего кода со второй точки println():

  • ваш код объявляет ArrayList типа Object;

  • Он добавляет Integer и String к ArrayList.

  • Он перечислил ваш список в список String. Ваш список помечен как String.

Генераторы Java - это функция времени компиляции, поэтому ваш список может принимать без каких-либо проблем элементы String и Integer. Сам объект ничего не знает о том, какие типы, которые он должен был содержать, в отличие от компилятора.

  1. Он пытается отыскать первый элемент вашего литого списка, который должен быть String и неявным образом отнести его к String.

  2. Вызывает println(String x) из класса PrintStream.

Но этот первый элемент на самом деле не является String и является Integer. Вы не можете использовать Integer для String.

Прочитайте Пример генерации в Java.