为什么Java基本类型是';公共、抽象和最终修饰符?

为什么Java基本类型是';公共、抽象和最终修饰符?,java,reflection,Java,Reflection,在对Java类型进行反思的过程中,我遇到了一个我不理解的奇怪现象 检查int的修饰符将返回public、abstract和final。我理解public和final,但是在原语类型上存在abstract对我来说并不明显。为什么会这样 编辑:我不是在思考Integer,而是在思考int: import java.lang.reflect.Modifier; public class IntegerReflection { public static void main(final Str

在对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

如果反射到从抽象类继承的类中,然后尝试挖掘该实例的基类,则在抽象类中定义为抽象的属性将没有值,但它是类定义的一部分

举个例子:

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,那么它必须是抽象的,如果您查看concreteClass.GetID(),那么它将是公共的。 希望这对你有所帮助。

如果你跑步的话

System.out.println(Modifier.toString(int.class.getModifiers()));
你得到

public abstract final
可能是因为你不能对它进行子分类,比如final,你也不能实例化它,比如abstract

从甲骨文的

抽象类不能实例化,但可以子类化

事实上,这也是它的最终手段,它不能是子类。

根据:

抽象类是不完整或被认为不完整的类

根据定义,不能有
int.class
的实例。您无法编译此类代码:

int a = new int();
int
没有构造函数。没有创建任何对象
int.class
甚至不扩展
对象
。如果运行以下代码行,结果将是
null

System.out.println(int.class.getSuperclass());
因此,因为您永远不可能拥有
int.class
的真实实例,所以根据定义,它是
抽象的
。此外,根据,Integer.TYPE字段(保存
int.class
)是一个仅表示基元类型的类

以下代码证明了这一点:

int a = 4;
System.out.println(int.class.isInstance(a));
这将返回
false

因此,
int.class
很可能仅用于系统中的表示目的,如
Integer
API中所述。还有一个
void.class
类型,但没有
null.class
类型,这一事实使我认为它主要用于反射。不过,这只是猜测


如果有人感兴趣,那么
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());
    }
}

int.class
也可以作为
Integer.TYPE
访问,并且是表示基元类型
int
的类实例

鉴于您无法实例化此类的对象(因为int不是实例,它们是基本类型),我认为将类型标记为
abstract
是有意义的

目前,我在《尽管》中找不到这方面的参考。

来自JVM规范: 抽象类是不完整的类,或认为不完整的类。 只有抽象类可以有抽象方法,也就是, 已声明但尚未实现的方法

如果一个类的定义是完整的,并且不需要或不需要任何子类,则可以将其声明为final。因为最后一节课从来没有 任何子类,最终类的方法都不能在 子类。类不能既是最终类又是抽象类,因为 这样一个类的实现永远无法完成

根据类的定义,类不能同时是抽象的和最终的。但是,JVM似乎没有将基元类型视为类,这在技术上是正确的,因为基元类型是而不是类,并且由JVM提供给语言运行时(使用
类getPrimitiveClass(const char*name)

因此,
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规范中关于原语类型为什么是
抽象的理论是因为它们被认为是不完整的

可能这只是
基本类
普通类
不同的一个特殊标记

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();
}
mirror::Class*ClassLinker::InitializePrimitiveClass(ObjPtr primitive_类,
基元::类型(类型){
Handle h_类(hs.NewHandle(primitive_类));
//公开最终静态
h|U类->设置访问标志(kAccPublic | kAccFinal | kAccAbstract);
h_类->SetPrimitiveType(类型);
h_class->SetIfTable(GetClassRoot(kJavaLangObject)->GetIfTable());
// ...
返回h_类。Get();
}
为什么Java基元类型的修饰符是公共的、抽象的和最终的

Class.getModifiers()的Java 11声明:

如果基础类是数组类,则其
公共
私有
受保护
修饰符与其组件类型的修饰符相同。如果此
表示基元类型或
无效
,则其
公共
修饰符始终为true,其
受保护
私有
修饰符始终为false。如果此对象表示数组类、基元类型或
void
,则其
final
修饰符始终为true,其
接口
修饰符始终为false其其他修饰符的值不由本规范确定

因此javadoc指定基本类型为
public
final
。这是很直观的。这将是在这两种情况下作出选择的原因

从技术上讲,
abstract