Почему метод getInterfaces () java.lang.Class возвращает Class [], А не Class []?

(Чтобы прояснить вопрос, «T» относится к параметру типа, объявленному в Class)

В качестве примера просмотрите следующее приложение:

public class TestClass {

    interface InterfaceA{}

    interface InterfaceB{}

    interface InterfaceC{}

    class ClassA implements InterfaceA, InterfaceB,  InterfaceC{}


    public static void main(String[] args){    

        Class<? super ClassA> superClass1 = ClassA.class;
        Class<? super ClassA> superclass2 = InterfaceA.class;
        Class<? super ClassA> superclass3 = InterfaceB.class;
        Class<? super ClassA> superclass4 = InterfaceC.class;

        for(Class<?> clazz : ClassA.class.getInterfaces()){
            System.out.println(clazz.getName());
        }   
    }
}

Результат такой же, как и следовало ожидать:

TestClass$InterfaceA
TestClass$InterfaceB
TestClass$InterfaceC

Итак, основываясь на этом примере выше, мы можем видеть, что компилятор распознает, что InterfaceA действительно соответствует границам подстановочного знака, как и все другие интерфейсы.

Интуитивно я ожидал, что следующее будет безопасным, но это не так:

Class<? super ClassA>[] interfaces = ClassA.class.getInterfaces();

Компилятор выдает предупреждение, потому что подпись говорит, что он возвращает Class; однако в javadoc для класса указано следующее:

Если этот объект представляет класс, возвращаемое значение представляет собой массив , содержащий объекты, представляющие все интерфейсы, реализованные классом .

«Этот объект» в нашем случае относится к ClassA . Основываясь на этом утверждении, если мы вызовем:

ClassA.class.getInterfaces()

, то мы логически знаем, что каждый Class в возвращаемом массиве будет содержать ссылку на супертип ClassA .

В качестве дополнительной справочной информации:

Из Справочника по языку Java, третье издание:

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

Читая эту и другие части спецификации, я мог бы подумать, что любой класс или интерфейс, реализованный или расширенный классом T , попадет в пределы .

ИЗМЕНИТЬ:

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

1    import java.util.Map;
2    import java.util.HashMap;
3    
4    public class MapWrapper<T> {
5        private final Map<Class<?>, OtherClass<T,?>> map = new HashMap <Class<?>, OtherClass<T,?>>();
6    
7        public <W> void addToMap(Class<W> type, OtherClass<T,? super W> otherClass){
8            map.put(type, otherClass);
9        }
10    
11        public <W> OtherClass<T,? super W> getOtherClassForAnyInterface(Class<W> type){
12            if(type.getInterfaces()!=null){
13                for(Class<?> interfaceType : type.getInterfaces()){
14                    // Here, a cast is necessary.  It throws a compiler warning for unchecked operations (rightfully so)
15                    OtherClass<T,? super W> otherClass = (OtherClass<T,? super W>)getOtherClassForInterface(interfaceType);
16                    if(null!=otherClass){
17                        return otherClass;
18                    }
19                }
20            }
21            return null;
22        }
23    
24        
25        public class OtherClass<T,V> {}
26    
27    }

Проблема в строке 15. Вы должны привести к , чтобы получить правильный тип. Предупреждение компилятора можно подавить, но оправдано ли это? Есть ли сценарий, при котором это приведение неверно?

12
задан Jeff Axelrod 5 May 2012 в 12:35
поделиться