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
修饰符必须是 true
,interface
修饰符必须是 false
) .另一方面,它没有为数组类型指定abstract
或static
修饰符,这意味着返回true
或false
的决定没有记录在JDK 中。因此,任何实现都可以选择返回true
或false
。
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:
-
索引可访问性
Cloneable
和 Serializable
的实现
但是除了语言本身之外没有人可以实现这些,因为我们自己不能真正声明一个实现。
【讨论】:
【参考方案5】:据我了解,getModifier() 的 java 语言规范是:
如果底层类是一个数组类,那么它的public,private 和 protected 修饰符与其组件类型的修饰符相同。 如果此类表示原始类型或 void,则其 public 修饰符 始终为真,其受保护和私有修饰符始终为 假的
现在,它的其他修饰符的值不是由本规范决定的,例如摘要。
来自 JVMS 表 4.1-A:
ACC_ABSTRACT 0x0400 声明的摘要;不得实例化。
【讨论】:
以上是关于isAbstract() 修饰符返回不正确的结果 - 为啥?的主要内容,如果未能解决你的问题,请参考以下文章