为什么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 ”表示“是一个直接的子类型”):

  • 如果ST都是引用类型,则S[] > 1 T[]如果S > 1 T
  • Object > 1 Object[]
  • Cloneable > 1 Object[]
  • java.io.Serializable > 1 Object[]
  • 如果p是基本类型,则:
    • Object > 1 p[]
    • Cloneable > 1 p[]
    • java.io.Serializable > 1 p[]

您的问题的重要部分是第一项:数组类型X[]是数组类型Y[]的子类型,当且仅当组件类型X是组件类型Y的子类型时。

另请注意,严格来说, Object[]String[]都不是类。 它们是“唯一”类型。 虽然每个类隐式都是一个类型,但反之则不然。 另一个不是类的类型的例子是基本类型: booleanbytecharshortintlongfloatdouble是类型,但它们不是类。

造成混淆的另一个原因是您可以轻松获取表示这些类型的 java.lang.Class对象。 再说一遍:这并不意味着那些类型是类。

在Java(和.NET)中,数组是协变的。 这意味着如果Appleinheritance了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对象。 链接