为什么Object .class.isAssignableFrom(String .class)== true?
为什么Object[].class.isAssignableFrom(String[].class) == true
,而String[].getSuperClass()
或getGenericInterfaces()
无法获取Object[]
?
我检查了JDK的来源,但我认为我自己无法得到答案。 现在,我知道JDK使用树来存储Classes之间的关系,并使用深度来指示它的级别, Class::isAssignableFrom()
搜索链,所以绝对数组在那个树中。 并且String[]
连接到Object[]
。
我可以说String[]
是Object[]
的子类吗? 或者它只是Java的另一个奇怪的东西?
Class.isAssignableFrom()
实质上检查子类型关系 。 “subtype”和“subclass”是两个不同的概念。 类层次结构(即子类化)只是子类型的一部分。
基元类型和数组类型具有子类型的特殊情况。
数组类型的子类型规则是这样的(注意“> 1 ”表示“是一个直接的子类型”):
- 如果
S
和T
都是引用类型,则S[]
> 1T[]
如果S
> 1T
Object
> 1Object[]
Cloneable
> 1Object[]
java.io.Serializable
> 1Object[]
- 如果
p
是基本类型,则:
Object
> 1p[]
Cloneable
> 1p[]
java.io.Serializable
> 1p[]
您的问题的重要部分是第一项:数组类型X[]
是数组类型Y[]
的子类型,当且仅当组件类型X
是组件类型Y
的子类型时。
另请注意,严格来说, Object[]
和String[]
都不是类。 它们是“唯一”类型。 虽然每个类隐式都是一个类型,但反之则不然。 另一个不是类的类型的例子是基本类型: boolean
, byte
, char
, short
, int
, long
, float
和double
是类型,但它们不是类。
造成混淆的另一个原因是您可以轻松获取表示这些类型的 java.lang.Class
对象。 再说一遍:这并不意味着那些类型是类。
在Java(和.NET)中,数组是协变的。 这意味着如果Apple
inheritance了Fruit
你可以将Apple[]
类型的实例传递给期望Fruit[]
的方法。 以下行有效:
Fruit[] fruits = apples; // apples is an Apple[]
这意味着Fruit[]
可以从Apple[]
分配。
当然,这不是很安全。 假设:
void someMethod(Object[] objects) { objects[0] = "Hello World"; // throws at run time. } void test() { Integer[] integers = new Integer[10]; integers[0] = 42; someMethod(integers); // compiles fine. }
当您想要使用数组内容(例如打印它)但不修改它时,此设计决策很方便。
因为String[]
实际上可以转换/扩展为Object[]
。
您可能认为这测试String[]
是否可以从Object[]
分配, 但它实际上测试反向(如果String[]
可以分配给 Object[]
)。
此代码按预期编译和执行:
public static void main(String[] args) { String[] strings = new String[]{ "hello", "world" }; printArray(strings); } public static void printArray(Object[] array) { for (Object obj : array) { System.out.println(obj); } }
如果此对象表示数组类,则返回表示Object类的Class对象。 链接