Я играл с дженериками и обнаружил, что, к моему удивлению, следующий код компилируется:
class A {}
class B extends A {}
class Generic<T> {
    private T instance;
    public Generic(T instance) {
        this.instance = instance;
    }
    public T get(){ return instance; }
}
public class Main {
    public static void main(String[] args) {
        fArray(new B[1], new Generic<A>(new A())); // <-- No error here
    }
    public static <T> void fArray(T[] a, Generic<? extends T> b) {
        a[0] = b.get();
    }
}
Я ожидал бы, что T будет выведен на B. A не распространяется B. Так почему компилятор не жалуется на это?
 T, как представляется, выводится на Object, так как я могу передать a Generic<Object>.
Кроме того,  при фактическом запуске кода он выдает ArrayStoreException в строке a[0] = b.get();.
Я не использую сырые общие типы. Я чувствую, что этого исключения можно было избежать с ошибкой времени компиляции или, по крайней мере, предупреждением, если T было фактически выведено как B.
При дальнейшем тестировании с эквивалентом List<...>:
public static void main(String[] args) {
    fList(new ArrayList<B>(), new Generic<A>(new A())); // <-- Error, as expected
}
public static <T> void fList(List<T> a, Generic<? extends T> b) {
    a.add(b.get());
}
Это приводит к ошибкам:
The method fList(List<T>, Generic<? extends T>) in the type Main is not applicable for the arguments (ArrayList<B>, Generic<A>)
Как и более общий случай:
public static <T> void fList(List<? extends T> a, Generic<? extends T> b) {
    a.add(b.get()); // <-- Error here
}
Компилятор правильно распознает, что первый ? может быть ниже иерархии наследования, чем второй ?.
например. Если первый ? был B, а второй ? был A, тогда это не безопасно для типа.
Так почему же первый пример не создает аналогичную ошибку компилятора? Это просто надзор? Или существует техническое ограничение?
Единственный способ, которым я мог создать ошибку, - это явно указать тип:
Main.<B>fArray(new B[1], new Generic<A>(new A())); // <-- Not applicable
Я действительно ничего не нашел в своих исследованиях, кроме этой статьи с 2005 года (до дженериков), в котором говорится о опасности ковариации массива.
Ковариация массивов, похоже, намекает на объяснение, но я не могу думать об этом.
Текущий jdk равен 1.8.0.0_91