Why are Java primitive types' modifiers `public`, `abstract`, & `final`?
According to the JLS 8.1.1.1 - Abstract Classes:
An abstract class is a class that is incomplete, or to be considered incomplete.
By definition, there can be no instances of int.class
. You can't compile this kind of code:
int a = new int();
There are no constructors for int
. There are no objects created. int.class
does not even extend Object
. If you run the following line of code, you will get null
as the result.
System.out.println(int.class.getSuperclass());
So because you can never have a true instance of the int.class
, it is by definition abstract
. Also, according to the Integer API, the Integer.TYPE
field (which holds int.class
) is a class which only represents the primitive type.
This is proven by the following code:
int a = 4;
System.out.println(int.class.isInstance(a));
This returns false
.
As such, int.class
is likely just used in the system for representation purposes, as said in the Integer
API. The fact that there is also a void.class
type but no null.class
type makes me think that this is used primarily with Reflection. This is just conjecture, though.
If anyone is interested, the int.class
essentially contains nothing that the reflection package recognizes and is likely just a dummy class. If you run the following code, you will see that it has no constructors, no fields, and no methods.
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());
}
}
If you run
System.out.println(Modifier.toString(int.class.getModifiers()));
you get
public abstract final
possibly because you can't sub-class it - i.e. final, and you can't instantiate it - i.e. abstract.
From Oracle's Abstract Methods and Classes
Abstract classes cannot be instantiated, but they can be subclassed.
The fact is its also final means it cannot be sub-classes.
From JVM Specifications:
An abstract class is a class that is incomplete, or considered incomplete. Only abstract classes may have abstract methods, that is, methods that are declared but not yet implemented.
A class can be declared final if its definition is complete and no subclasses are desired or > required. Because a final class never has any subclasses, the methods of a final class cannot be overridden in a subclass. A class cannot be both final and abstract, because the implementation of such a class could never be completed.
According to specifications a class cannot be both Abstract and Final. But however, it seems like JVM does not treat primitive types as classes, which is technically correct since primitive types are not classes and are supplied to the language runtime by the JVM(using Class getPrimitiveClass(const char *name)
).
So int
, and every other primitive type,
> 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`.
My theory from the JVM specification for why primitive types are abstract
is because, they're considered incomplete.