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.