Почему генерические средства Java не допускают преобразование типов в общие типы?

public class Main {

    public static <T> void foo(T[] bar) {
        double d = (double) bar[0]; // Error : incompatible types
    }

    public static void main(String[] args) {
        int[] int_buf = new int[8];
        foo(int_buf);
    }
}

Проблема указывается в коде.

Почему дженерики Java не допускают преобразование типов в общие типы?

Ответ 1

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

Если вы переходите на <T extends Number>, это должно работать нормально. Хотя, возможно, вам понадобится массив Integer, а не массив int

Ответ 2

Проблема глубже, чем это. Даже без выделенной строки эта программа не работает:

public class Main {
    public static <T> void foo(T[] bar) {
        // do nothing
    }

    public static void main(String[] args) {
        int[] int_buf = new int[8];
        foo(int_buf);   <-- problem is here
   }
}

Генераторы Java поддерживают только ссылочные типы как параметры типа; общий метод foo() можно переписать следующим образом:

<T extends Object> void foo(T[] bar) { ... }

И вот ваша проблема: нет T, которая расширяет Object таким образом, что int[] является T[].

Во-вторых, причина, по которой конверсия также терпит неудачу, заключается в том, что мы ничего не знаем о T, поэтому мы не знаем, что существует преобразование от T до double.

Ответ 3

Компилятор Java стирает все параметры типа в общем коде. Прямым следствием этого является то, что вы не можете проверить, какой параметризованный тип для общего в настоящее время используется. Если вы проверите, instanceof тоже не будет работать. Так как runtime не отслеживает параметры типа в java, нет разницы между HashSet<Integer> и HashSet<Double>. Вы можете сделать ..instanceof HashSet<?> максимум, чтобы проверить, является ли это экземпляром HashSet.

Если что-то непонятно в том, что я написал, обратитесь к docs.