Странная ошибка при инициализации списка

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

Вот код:

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

import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;

public class Test {

    public static void main(String[] args) {
        /**
        * This line shows this compilation error in eclipse:
        * Type mismatch: cannot convert from 
        *     List<Class<? extends JComponent&Accessible>> 
        *          to List<Class<? extends JComponent>>
        */
        List<Class<? extends JComponent>> listComp = Arrays.asList(JTabbedPane.class, 
                                                                   JPanel.class);

        /**
        * This one compiles fine and the difference is that
        * he added JComponent.class on the list and the 
        * code is working fine
        */
        List<Class<? extends JComponent>> listComp2 = Arrays.asList(JTabbedPane.class, 
                                                                    JPanel.class, 
                                                                    JComponent.class);
    }

}

Как вы можете видеть, единственное отличие состоит в том, что во второй переменной списка мы добавили JComponent.class, и ошибка исчезла.

Почему это?

Обновление

Мы используем обновление Java JDK 7 80

Обновление 2

Другой друг предложил этот кусок кода, и он также работает:

List<Class<? extends JComponent>> listComp = 
      new ArrayList<Class<? extends JComponent>> ( Arrays.asList( JTabbedPane.class, 
                                                                  JPanel.class));

Ответ 1

Я могу дублировать эту проблему в Java 7, но когда я переключусь на Java 8, ошибка больше не указана. Кроме того, если я остаюсь в Java 7, но я даю аргумент типа Arrays.asList, ошибка больше не указана.

List<Class<? extends JComponent>> listComp =
    Arrays.<Class<? extends JComponent>>asList(JTabbedPane.class, JPanel.class);

Java попытается определить целевой тип возврата Arrays.asList. По-видимому, оба JTabbedPane и JPanel расширяют JComponent и реализуют Accessible. Однако JComponent не реализует Accessible. Результатом является наиболее полный, специфический тип, который компилятор может получить вместе со всеми типами. Для вашего первого примера выведенный тип List<Class<? extends JComponent & Accessible>>, потому что оба аргумента соответствуют этому типу. Когда вы добавляете JComponent, выводимый тип теперь List<Class<? extends JComponent>> и соответствует listComp, позволяя ему компилироваться в Java 7.

Java 8 улучшает вывод целевого типа. Этот пример учебника относится к Collections.emptyList, который передается методу, требующему List<String>. В Java 7 предполагаемый тип будет List<Object> и произойдет ошибка компиляции. Однако в Java 8, выводимый тип List<String>, сопоставление параметра метода и компиляции кода.

Это не совсем тот же пример, что и ваш код, но он достаточно близок, и я считаю, что в целом Java 8 улучшает вывод целевого типа, объясняет, почему код компилируется с этой версией.