466. Java 反射 - 类的规范名
1. 什么是 Canonical Name?
-
规范名(Canonical Name):在 Java 语言规范中定义,等价于 包名 + 类的简单名。
- 例如:
java.lang.String
- 例如:
- 它和 简单名(Simple Name) 的区别:
- 简单名:
String - 规范名:
java.lang.String
- 简单名:
⚠️ 并不是所有类都有规范名。以下几类没有规范名:
- 本地类(Local Class) —— 定义在方法中的类
-
匿名类(Anonymous Class) ——
new Object(){} - 隐藏类(Hidden Class) —— Java 15 引入的新特性
如果类没有规范名,getCanonicalName() 会返回 null。
2. 示例代码
import java.util.function.Supplier;
public class CanonicalNameDemo {
public static void main(String[] args) {
// 普通类
Class<?> c1 = String.class;
System.out.println("Canonical name: " + c1.getCanonicalName());
// 匿名类
Object key = new Object() {};
Class<?> c2 = key.getClass();
System.out.println("Canonical name: " + c2.getCanonicalName());
// Lambda 表达式
Supplier<String> supplier = () -> "Hello";
Class<?> c3 = supplier.getClass();
System.out.println("Canonical name: " + c3.getCanonicalName());
}
}
运行结果
Canonical name: java.lang.String
Canonical name: null
Canonical name: chapter466.Demo$$Lambda$1/2003749087
✅ 说明:
-
String是正常类 → 有规范名java.lang.String - 匿名类 → 没有规范名 → 返回
null - Lambda → 由编译器生成匿名类 → 也没有规范名 → 返回
null
3. 与其他名称方法对比
| 方法 | 输出示例(匿名类) | 输出示例(Lambda) | 输出示例(普通类) |
|---|---|---|---|
getName() |
pkg.Outer$1 |
pkg.Main$$Lambda$23/0x0000... |
java.lang.String |
getSimpleName() |
""(空字符串) |
Main$$Lambda$23/0x... |
String |
getCanonicalName() |
null |
null |
java.lang.String |
📌 口诀:
-
getName()→ JVM 内部名(最全) -
getSimpleName()→ 源码里的类名(匿名类为空) -
getCanonicalName()→ 规范名(可能为null)
4. 总结
-
getCanonicalName()用来获取类的 全限定名(包名 + 类名)。 - 匿名类、局部类、隐藏类没有规范名 → 返回
null。 - 在日志、框架内部通常优先使用
getCanonicalName(),因为它最接近源码中的“真实名字”。 - 如果你需要保证不为
null,用getName()更保险。