isAbstract() 修饰符返回不正确的结果 - 为啥?

Posted

技术标签:

【中文标题】isAbstract() 修饰符返回不正确的结果 - 为啥?【英文标题】:isAbstract() Modifier returning Incorrect result - Why?isAbstract() 修饰符返回不正确的结果 - 为什么? 【发布时间】:2018-12-23 15:21:13 【问题描述】:

据我了解,以下代码应将False 打印为输出

但是,当我运行此代码时,它会打印 True 作为输出。

来自 Java 文档:

如果整数参数包含抽象修饰符,则返回 true, 否则为假。

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

谁能帮我理解这种行为?

【问题讨论】:

是的,那么它应该注意返回true,它应该是false。 有趣的发现... 我可以确认每个数组类型都是如此,包括多维数组 对此最好的解释是数组类是抽象的,因为与其他类不同,byte[] 实例不是由public class byte[] 类定义的。好吧,我现在不知道我在说什么xD public abstract final?很有趣。 【参考方案1】:

Javadoc of int java.lang.Class.getModifiers() 指定应该为数组类型的某些修饰符返回什么(例如,final 修饰符必须是 trueinterface 修饰符必须是 false) .另一方面,它没有为数组类型指定abstractstatic 修饰符,这意味着返回truefalse 的决定没有记录在JDK 中。因此,任何实现都可以选择返回truefalse

int java.lang.Class.getModifiers()

返回此类或接口的 Java 语言修饰符,以整数编码。修饰符由 Java 虚拟机的 public、protected、private、final、static、abstract 和 interface 常量组成;它们应该使用修饰符类的方法进行解码。

如果底层类是数组类,那么它的public、private和protected修饰符与其组件类型的修饰符相同。如果此类表示原始类型或 void,则其 public 修饰符始终为 true,其 protected 和 private 修饰符始终为 false。 如果此对象表示数组类、原始类型或 void,则其 final 修饰符始终为 true,其接口修饰符始终为 false其其他修饰符的值不由本规范确定。

修饰符编码在 Java 虚拟机规范的表 4.1 中定义。

【讨论】:

对于那些挖掘出实际规格并向我指出我还不知道的事情的人总是 +1。【参考方案2】:

可以在 JLS 10.8. Class Objects for Arrays 中找到有关此行为的提示:

每个数组都有一个关联的 Class 对象,与具有相同组件类型的所有其他数组共享。

虽然数组类型不是类,但每个数组的 Class 对象表现得好像:[snipped]

根据这种推理,数组不是“真正的”类,因此它绝对不是具体的类。同样的逻辑也适用于被视为抽象的int.class

【讨论】:

【参考方案3】:

abstract 的定义说:

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

如果有像[] 这样的纯数组,那么它确实是不完整的,因为没有提供组件类型。

这将违反15.10.1. Array Creation Expressions的规范:

如果 ClassOrInterfaceType 不表示是编译时错误 可具体化的类型。

它不仅表示可具体化的类型,而且根本不表示类型。因此不可能创建[] 的实例——就像抽象类一样。

由于没有纯数组[],这只是一种推测。此外,为byte[] 返回了修饰符。它仍然是 Eran 显示的规范。

【讨论】:

【参考方案4】:

我的解释是,数组被认为是abstract,因为它们是由 JVM 本身实例化的。

对于任何数组类型都不存在具体的类。

一个数组有一个contract defined by the JLS:

    索引可访问性 CloneableSerializable 的实现

但是除了语言本身之外没有人可以实现这些,因为我们自己不能真正声明一个实现。

【讨论】:

【参考方案5】:

据我了解,getModifier() 的 java 语言规范是:

如果底层类是一个数组类,那么它的public,private 和 protected 修饰符与其组件类型的修饰符相同。 如果此类表示原始类型或 void,则其 public 修饰符 始终为真,其受保护和私有修饰符始终为 假的

现在,它的其他修饰符的值不是由本规范决定的,例如摘要

来自 JVMS 表 4.1-A:

ACC_ABSTRACT 0x0400 声明的摘要;不得实例化。

【讨论】:

以上是关于isAbstract() 修饰符返回不正确的结果 - 为啥?的主要内容,如果未能解决你的问题,请参考以下文章

python 将命名修饰符切换为ON或OFF。一个典型的用途是使用性能密集的修饰符,而不是在工作/预览结果时关闭

RegExp对象

第三节 java 函数

方法和数组

Java方法覆盖重写

Python classmethod 修饰符