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

Java: экспериментирование с дженериками

Наконец, я немного экспериментирую с дженериками. Я придумал этот фрагмент кода:

public class Test {

    static <T> void f(T x) {
        x = (T) (Integer) 1234;
        System.out.println(x);
    }

    public static void main(String[] args) {
        f("a");
        f(1);
        f('a');
        f(1.5);
        f(new LinkedList<String>());
        f(new HashMap<String, String>());
    }
}

Я запустил это и получил этот вывод:

1234
1234
1234
1234
1234
1234

без исключений! Как это возможно?

4b9b3361

Ответ 1

Это из-за типа стирания (об этом написано много, просто Google для этого термина). После компиляции f в байтовый код метод может выглядеть следующим образом:

static void f(Object x) {
    x = (Object) (Integer) 1234;
    System.out.println(x);
}

Итак System.out.println просто вызовет метод toString на объекте x - и в вашем случае это Integer.toString().

Ответ 2

Из-за типа Erasure. Из Документация Oracle:

На язык Java были введены обобщения для обеспечения более жесткого типа проверяет время компиляции и поддерживает универсальное программирование. к реализовать generics, компилятор Java применяет стирание типа к:

  • Заменить все параметры типа в родовых типах своими границами или Объект, если параметры типа не ограничены. Произведенный байт-код, поэтому содержит только обычные классы, интерфейсы и методы.

  • При необходимости введите тип приведения, чтобы сохранить безопасность типа.

  • Создание мостовых методов для сохранения полиморфизма в расширенных общих типах.

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