Неверный результат, возвращаемый isAbstract() класса Modifier

Насколько я понимаю, следующий код должен печатать False, однако, когда я запускал этот код, он печатает True.

Из документов Java:

Возвращает true, если аргумент integer включает абстрактный модификатор, в противном случае - false.

public class Test{
    public static void main(String[] args) {
        System.out.println(Modifier.isAbstract(byte[].class.getModifiers())); 
    }
}

Может ли кто-нибудь помочь мне понять это поведение?

Ответы

Ответ 1

Javadoc из int java.lang.Class.getModifiers() указывает, что должно быть возвращено для некоторых модификаторов для типов массивов (например, final модификатор должен быть true а модификатор interface должен быть false). С другой стороны, он не указывает, какие abstract или static модификаторы должны быть для типов массивов, а это означает, что решение о возврате true или false не документировано в JDK. Поэтому любая реализация может выбрать либо true либо false.

int java.lang.Class.getModifiers()

Возвращает модификаторы языка Java для этого класса или интерфейса, закодированные в целое число. Модификаторы состоят из констант виртуальной машины Java для общедоступных, защищенных, частных, конечных, статических, абстрактных и интерфейсов; они должны быть декодированы с использованием методов класса Modifier.

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

Кодировки модификаторов определены в Спецификации виртуальной машины Java, таблица 4.1.

Ответ 2

Указание на подобное поведение можно найти в JLS, 10.8. Объекты класса для массивов:

Каждый массив имеет связанный объект класса, совместно используемый всеми другими массивами с одним и тем же типом компонента.

Хотя тип массива не является классом, объект класса каждого массива действует так: [snipped]

Согласно этому рассуждению массив не является "реальным" классом, поэтому он определенно не является конкретным классом. Такая же логика применима к int.class который считается абстрактным.

Ответ 3

В определении абстрактного говорится:

Абстрактный класс - это неполный класс, который считается неполным.

Если бы существовал чистый массив, подобный [] то он был бы действительно неполным, поскольку не предоставляется тип компонента.

Это нарушит спецификацию 15.10.1. Выражения создания массива:

Это ошибка времени компиляции, если класс ClassOrInterfaceType не обозначает повторяемый тип.

Он не просто обозначает тип повторного типа, но не тип вообще. Таким образом, было бы невозможно создать экземпляры [] - точно так же, как для абстрактных классов.

Поскольку нет чистого массива [] это всего лишь предположение. Кроме того, модификаторы были возвращены для byte[]. Это остается спецификацией, показанной Эраном.

Ответ 4

Моя эксплантация будет состоять в том, что массивы считаются abstract поскольку они создаются самим JVM.

Просто нет конкретного класса для любого типа массива.

Массив имеет контракт, определенный JLS:

  1. Доступность индексов
  2. Реализация для Cloneable и Serializable

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

Ответ 5

Из моего понимания спецификация java языка для getModifier():

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

Теперь значения других модификаторов не определяются этой спецификацией, например, АБСТРАКТ.

Из таблицы JVMS 4.1-A:

ACC_ABSTRACT 0x0400 Объявленный реферат; не должны создаваться.