Java中的getClass方法与数组类型

26

我遇到了一个奇怪的问题,不知道它叫什么,所以很难找到相关的信息,因此我在这里提问。

在Java中,如果你创建一个任意类型的数组,并调用getClass方法,你会得到一个奇怪的返回值。我想知道为什么会出现这种特殊的返回值,以及它的含义是什么。

以下是代码示例:

byte[] me = new byte[1];
int[] me2 = new int[1];
double[] me3 = new double[1];
float[] me4 = new float[1];
String[] me5 = new String[1];
Integer[] me6 = new Integer[1];

System.out.println(me.getClass());                  
System.out.println(me2.getClass());                 
System.out.println(me3.getClass());                 
System.out.println(me4.getClass());                 
System.out.println(me5.getClass());
System.out.println(me6.getClass());

输出结果为:

 class [B
 class [I
 class [D
 class [F
 class [Ljava.lang.String;
 class [Ljava.lang.Integer;
5个回答

30

Class的toString方法调用了Class的getName方法。

Returns the name of the entity (class, interface, array class, primitive type, or void) represented by this Class object, as a String. If this class object represents a reference type that is not an array type then the binary name of the class is returned, as specified by The Java™ Language Specification.

If this class object represents a primitive type or void, then the name returned is a String equal to the Java language keyword corresponding to the primitive type or void.

If this class object represents a class of arrays, then the internal form of the name consists of the name of the element type preceded by one or more '[' characters representing the depth of the array nesting. The encoding of element type names is as follows:

 Element Type           Encoding
 boolean                Z
 byte                   B
 char                   C
 class or interface     Lclassname;
 double                 D
 float                  F
 int                    I
 long                   J
 short                  S 

The class or interface name classname is the binary name of the class specified above.

Examples:

 String.class.getName()
     returns "java.lang.String"
 byte.class.getName()
     returns "byte"
 (new Object[3]).getClass().getName()
     returns "[Ljava.lang.Object;"
 (new int[3][4][5][6][7][8][9]).getClass().getName()
     returns "[[[[[[[I"

10

这只是一些愚蠢的命名惯例。如果它们更易于人类阅读,那将会更好:class byte[]class java.lang.Integert[][]


1

这些是底层类型对象的名称。 [ 表示它是一个数组,接下来的字母表示数组类型。 B=byte,I=integer,D=double 等等。正如您所看到的,“L”用于类类型成员。


1

类名开头的 [ 应该被读作 "array of ...",其中 "..." 是跟在 [ 后面的内容;关于后面应该跟什么的惯例在 @emory 提到并链接到的 Class.getName() 文档中有说明。

Java 语言规范第 4.3.1 节 开始说:"对象是类实例或数组。" 这表明数组不是类实例。(也许这就是 @TigerTrussell 在他的答案中所指的。)然而,第 10.8 节 开始说:"每个数组都有一个关联的 Class 对象,与所有具有相同组件类型的其他数组共享。数组类型的直接超类是 Object。" 这表明数组,如果不算真正的类实例,那也非常接近了。

不幸的是,Java 的语法规则禁止从数组类型继承:

public class MyFancyArray extends int[] { // ILLEGAL
   // ...
}

请注意,这是一种语法限制;没有概念或语义障碍(在许多其他面向对象的编程语言中也允许使用)。

-3

数组没有类,它们只是数据结构。唯一拥有类的是从包含在数组中的Object扩展而来的东西。


抱歉——你得到奇怪的输出是因为Java组织其数据结构的基本方式。字母对应于数据类型,而它们前面的'['表示它是一个数组。 - TigerTrussell
2
数组绝对是对象。例如,这样做非常合理:int[] a = new int[3]; System.out.println(a.getClass().getName()); - Ted Hopp
这取决于你的观点。使用 int[].class 是完全合法的。 - aroth
我不同意。如果数组没有类,那么为什么Class方法有一个isArray方法来确定该Class对象是否表示数组类。--http://download.oracle.com/javase/1,5.0/docs/api/java/lang/Class.html#isArray%28%29 - emory
1
@TigerTrussell - 谁说你必须是一个对象才能拥有一个类?int并不是一个合适的对象(尽管自动装箱除外),但它仍然有一个类。如果你想在技术上讲究一点,每个对象(和原始类型)只是为给定类型分配的连续内存块。 - aroth
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接