1. 概述
在本文中,我们将介绍 Java 中 Class
类提供的四种获取类名的方法:getSimpleName()
、getName()
、getTypeName()
和 getCanonicalName()
。
这些方法由于名称相似,加上 JavaDoc 描述不够明确,常常让人感到困惑。而且在处理基本类型、对象类型、内部类、匿名类和数组时,它们的行为也存在一些微妙的差异。
2. 获取简单类名
我们先从 getSimpleName()
方法开始。
Java 中的类名分为两类:简单名称(simple name)和限定名称(qualified name)。简单名称就是一个标识符,而限定名称则是由多个简单名称通过点号(.
)连接而成。
顾名思义,getSimpleName()
返回的是类的简单名称,也就是类在源码中定义的名字。
例如有如下类:
package com.baeldung.className;
public class RetrieveClassName {}
调用 getSimpleName()
会返回 "RetrieveClassName"
:
assertEquals("RetrieveClassName", RetrieveClassName.class.getSimpleName());
✅ 对于基本类型(如 int
, boolean
, float
),该方法直接返回其类型名。
✅ 对于数组类型,则会在元素类型的简单名称后追加相应数量的 []
:
RetrieveClassName[] names = new RetrieveClassName[0];
assertEquals("RetrieveClassName[]", names.getClass().getSimpleName());
⚠️ 对于匿名类,调用 getSimpleName()
会返回一个空字符串 ""
。
3. 获取其他类型的类名
接下来我们看看 getName()
、getTypeName()
和 getCanonicalName()
这三个方法。它们提供了比 getSimpleName()
更多的信息。
3.1. 基本类型
对于基本类型,这四个方法的返回值是完全一致的,都返回类型的名称:
assertEquals("int", int.class.getName());
assertEquals("int", int.class.getTypeName());
assertEquals("int", int.class.getCanonicalName());
3.2. 对象类型
对于普通对象类型,这三种方法的行为也基本一致:返回类的全限定名(canonical name)。
例如:
assertEquals("com.baeldung.className.RetrieveClassName", RetrieveClassName.class.getName());
assertEquals("com.baeldung.className.RetrieveClassName", RetrieveClassName.class.getTypeName());
assertEquals("com.baeldung.className.RetrieveClassName", RetrieveClassName.class.getCanonicalName());
3.3. 内部类
对于内部类,情况有所不同:
getCanonicalName()
依然返回标准的全限定名,使用点号分隔外部类与内部类:assertEquals("com.baeldung.RetrieveClassName.InnerClass", RetrieveClassName.InnerClass.class.getCanonicalName());
而
getName()
和getTypeName()
则使用美元符号$
作为分隔符:assertEquals("com.baeldung.RetrieveClassName$InnerClass", RetrieveClassName.InnerClass.class.getName()); assertEquals("com.baeldung.RetrieveClassName$InnerClass", RetrieveClassName.InnerClass.class.getTypeName());
3.4. 匿名类
匿名类是另一个特殊场景:
getSimpleName()
返回空字符串""
getCanonicalName()
返回null
getName()
和getTypeName()
返回外部类名 +$
+ 一个数字(表示该匿名类在外部类中的定义顺序)
示例:
assertEquals("com.baeldung.Main$1", new RetrieveClassName() {}.getClass().getName());
assertEquals("com.baeldung.Main$2", new RetrieveClassName() {}.getClass().getTypeName());
3.5. 数组类型
对于数组,三种方法的处理方式如下:
getTypeName()
和getCanonicalName()
会在元素类型后面追加对应维度的[]
:assertEquals("com.baeldung.RetrieveClassName$InnerClass[][]", RetrieveClassName.InnerClass[][].class.getTypeName()); assertEquals("com.baeldung.RetrieveClassName.InnerClass[][]", RetrieveClassName.InnerClass[][].class.getCanonicalName());
getName()
的规则则比较特殊:- 对于基本类型数组,返回的是 JVM 内部表示,例如
[[I
表示二维int
数组 - 对于对象数组,格式为
[L
+ 全限定类名 +;
- 对于基本类型数组,返回的是 JVM 内部表示,例如
示例:
assertEquals("[[I", int[][].class.getName());
assertEquals("[Lcom.baeldung.className.RetrieveClassName;",
RetrieveClassName[].class.getName());
4. 总结
本文介绍了 Java 中获取类名的四种常用方法:
方法名 | 用途说明 |
---|---|
getSimpleName() |
获取类的简单名称(源码中定义的名字) |
getName() |
获取 JVM 内部使用的类名(可能包含 $ ) |
getTypeName() |
获取类型名称,主要用于泛型、数组等场景 |
getCanonicalName() |
获取标准的全限定类名,符合 Java 语言规范 |
简单来说,如果你只需要类名本身,用 getSimpleName()
;如果需要完整路径或用于反射,推荐使用 getName()
或 getCanonicalName()
。
📌 本文代码示例可参考 GitHub 项目。