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 + 全限定类名 + ;

示例:

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 项目


原始标题:Retrieving a Class Name in Java