Почему модификаторы примитивов Java являются "public", "abstract" и "final"?
В процессе некоторого размышления о типах Java я сталкивался с странностью, которую я не понимаю.
Проверка int
для его модификаторов возвращает public
, abstract
и final
. Я понимаю public
и final
, но наличие abstract
для примитивного типа для меня неочевидно. Почему это так?
Изменить: я не задумываюсь о Integer
, а о int
:
import java.lang.reflect.Modifier;
public class IntegerReflection {
public static void main(final String[] args) {
System.out.println(String.format("int.class == Integer.class -> %b", int.class == Integer.class));
System.out.println(String.format("int.class modifiers: %s", Modifier.toString(int.class.getModifiers())));
System.out.println(String.format("Integer.class modifiers: %s", Modifier.toString(Integer.class.getModifiers())));
}
}
Выход при запуске:
int.class == Integer.class -> false
int.class modifiers: public abstract final
Integer.class modifiers: public final
Ответы
Ответ 1
Если вы запустите
System.out.println(Modifier.toString(int.class.getModifiers()));
вы получаете
public abstract final
возможно потому, что вы не можете подклассифицировать его - то есть final, и вы не можете его создать, т.е. абстрактно.
Из Oracle Абстрактные методы и классы
Абстрактные классы не могут быть созданы, но они могут быть подклассами.
Дело в том, что он также окончательный означает, что он не может быть подклассами.
Ответ 2
В соответствии с JLS 8.1.1.1 - Абстрактные классы:
Абстрактный класс является неполным или считается неполным.
По определению не может быть экземпляров int.class
. Вы не можете скомпилировать этот код:
int a = new int();
Нет конструкторов для int
. Созданных объектов нет. int.class
даже не расширяется Object
. Если вы запустите следующую строку кода, вы получите null
в качестве результата.
System.out.println(int.class.getSuperclass());
Итак, поскольку у вас никогда не может быть истинного экземпляра int.class
, он по определению abstract
. Кроме того, в соответствии с Integer API поле Integer.TYPE
(которое содержит int.class
) является классом, который представляет только примитивный тип.
Это подтверждается следующим кодом:
int a = 4;
System.out.println(int.class.isInstance(a));
Это возвращает false
.
Таким образом, int.class
скорее всего используется в системе для целей представления, как сказано в API Integer
. Тот факт, что существует также тип void.class
, но не тип null.class
, заставляет меня думать, что это используется в основном с Reflection. Это всего лишь гипотеза.
Если кому-то интересно, int.class
по существу не содержит ничего, что пакет отражения распознает и, скорее всего, просто фиктивный класс. Если вы запустите следующий код, вы увидите, что у него нет конструкторов, полей и методов.
Method[] intMethods = int.class.getMethods();
if(intMethods.length == 0) {
System.out.println("No methods.");
}
else {
for(Method method : intMethods) {
System.out.println(method.getName());
}
}
Constructor[] intConstructors = int.class.getConstructors();
if(intConstructors.length == 0) {
System.out.println("No constructors.");
}
else {
for(Constructor constructor: intConstructors) {
System.out.println(constructor.getName());
}
}
Field[] intFields = int.class.getFields();
if(intFields.length == 0) {
System.out.println("No fields.");
}
else {
for(Field field: intFields) {
System.out.println(field.getName());
}
}
Ответ 3
Из спецификации JVM:
Абстрактный класс - неполный неполный класс или считается неполным. Только абстрактные классы могут иметь абстрактные методы, т.е. которые объявлены, но еще не реализованы.
Класс может быть объявлен окончательным, если его определение завершено и никаких подклассов не требуется или требуется. Потому что у последнего класса никогда не было любые подклассы, методы последнего класса не могут быть переопределены в подкласс. Класс не может быть как окончательным, так и абстрактным, поскольку реализация такого класса никогда не может быть завершена.
В соответствии с спецификациями класс не может быть как абстрактным, так и финальным. Но, однако, похоже, что JVM не рассматривает примитивные типы как классы, что является технически корректным, поскольку примитивные типы являются не классами и предоставляются JVM языковой среде (с использованием Class getPrimitiveClass(const char *name)
).
So int
, и любой другой примитивный тип,
> a. Should be accessible from within the language: Make it `public`
> b. Should not be extensible : Make it `final`
> c. Should not be instantiated with `new` : Make it `abstract`.
Моя теория из спецификации JVM объясняет, почему примитивные типы abstract
- это потому, что они считаются неполными.
Ответ 4
int.class
также доступен как Integer.TYPE
и является экземпляром класса, представляющим примитивный тип int
.
Учитывая, что вы не можете создать экземпляр объекта этого класса (поскольку ints не являются экземплярами, они являются примитивными типами), я считаю, что имеет смысл иметь тип, помеченный abstract
.
На данный момент я не могу найти ссылку на ссылку JLS, хотя.
Ответ 5
Может быть, это просто особый знак для primitive class
отличный от normal class
.
Реализация кода JVM:
mirror::Class* ClassLinker::InitializePrimitiveClass(ObjPtr<mirror::Class> primitive_class,
Primitive::Type type) {
Handle<mirror::Class> h_class(hs.NewHandle(primitive_class));
// public final static
h_class->SetAccessFlags(kAccPublic | kAccFinal | kAccAbstract);
h_class->SetPrimitiveType(type);
h_class->SetIfTable(GetClassRoot(kJavaLangObject)->GetIfTable());
// ...
return h_class.Get();
}
Ответ 6
если вы отразились на класс, унаследованный от абстрактного класса, а затем попытались выкопать в базовый класс для этого экземпляра, свойство, определенное как абстрактное в абстрактном классе, не имеет значения, но оно является частью класса определение.
Вот пример:
public class absBase{
private string name;
private int ID;
public abstract int GetID();
}
public class concreteClass:absBase{
@Override
public int GetID(){
return ID + 1;
}
}
поэтому, если вы отражали absBase и смотрели на GetID, он должен был быть абстрактным по определению, если бы вы посмотрели на specificClass.GetID(), но он был бы общедоступным.
надеюсь, что это поможет.