Почему Object []. Class.isAssignableFrom (String []. Class) == true? - PullRequest
3 голосов
/ 30 октября 2009

Почему Object[].class.isAssignableFrom(String[].class) == true, а String[].getSuperClass() или getGenericInterfaces() не удалось получить Object[]?

Я проверил источник JDK, но я не думаю, что смогу получить ответ сам. На данный момент я знаю, что JDK использует дерево для хранения взаимосвязей между классами и глубину, чтобы указать его уровень, Class::isAssignableFrom() просматривал цепочку, поэтому определенно в этом дереве есть массивы. а также String[] подключен к Object[].

Могу ли я сказать, что String[] является подклассом Object[]? Или это просто еще одна странная вещь в Java?

Ответы [ 4 ]

6 голосов
/ 30 октября 2009

Class.isAssignableFrom() по существу проверяет отношение подтипа . «подтип» и «подкласс» - это два разных понятия. Иерархия классов (т.е. создание подклассов) является лишь частью подтипирования.

Примитивные типы и типы массивов имеют особые случаи для подтипирования.

Правила для подтипов типов массивов такие (обратите внимание, что "> 1 " означает "это прямой подтип"):

  • Если S и T являются ссылочными типами, то S[]> 1 T[] если S> 1 T.
  • Object> 1 Object[]
  • Cloneable> 1 Object[]
  • java.io.Serializable> 1 Object[]
  • Если p является примитивным типом, то:
    • Object> 1 p[]
    • Cloneable> 1 p[]
    • java.io.Serializable> 1 p[]

Важной частью вашего вопроса является самый первый элемент: тип массива X[] является подтипом типа массива Y[] тогда и только тогда, когда тип компонента X является подтипом типа компонента Y.

Также обратите внимание, что строго говоря, Object[] и String[] не являются классами. Это "только" типы. Хотя каждый класс неявно является типом, обратное неверно. Другим примером типов, которые не являются классами, являются примитивные типы: boolean, byte, char, short, int, long, float и double являются типами, но они не классы.

Другой причиной путаницы является тот факт, что вы можете легко получить java.lang.Class объектов, представляющих эти типы . Опять же: это не означает, что эти типы являются классами.

2 голосов
/ 30 октября 2009

В Java (и .NET) массивы ковариантны. Это означает, что вы можете передать экземпляр типа Apple[] методу, который ожидает Fruit[], если Apple наследует Fruit. Действительна следующая строка:

Fruit[] fruits = apples; // apples is an Apple[]

Это означает, что Fruit[] назначается из Apple[].

Конечно, это не очень безопасно. Предположим:

void someMethod(Object[] objects) {
    objects[0] = "Hello World"; // throws at run time.
}

void test() {
    Integer[] integers = new Integer[10];
    integers[0] = 42;
    someMethod(integers); // compiles fine.
}

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

0 голосов
/ 30 октября 2009

Если этот объект представляет класс массива, то возвращается объект Class, представляющий класс Object. link

0 голосов
/ 30 октября 2009

Поскольку String[] действительно может быть преобразовано / расширено до Object[].

Возможно, вы думаете, что этот тест проверяется, если String[] назначается из Object[], , но на самом деле проверяет обратное (если String[] может быть назначено Object[]).

Этот код компилируется и выполняется как ожидается:

public static void main(String[] args) {
    String[] strings = new String[]{ "hello", "world" };
    printArray(strings);
}

public static void printArray(Object[] array) {
    for (Object obj : array) {
        System.out.println(obj);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...