首页 > Java > 在Java中,这些之间有什么区别:Object o1 = …. o1.getClass().getSimpleName();o1.getClass().getName();o1.getClass().getCanonicalName();

在Java中,这些之间有什么区别:Object o1 = …. o1.getClass().getSimpleName();o1.getClass().getName();o1.getClass().getCanonicalName();

上一篇 下一篇

在Java中,这些之间有什么区别:

Object o1 = ....
o1.getClass().getSimpleName();
o1.getClass().getName();
o1.getClass().getCanonicalName();

我已经多次检查了Javadoc,但这从来没有很好地解释过它。
我还运行了一个测试,它并没有反映这些方法的调用方式背后的任何实际含义。

分割线

网友回答:

添加局部类、lambda 和方法以完成前两个答案。此外,我添加了 lambda 数组和匿名类数组(尽管在实践中没有任何意义):toString()

package com.example;

public final class TestClassNames {
    private static void showClass(Class<?> c) {
        System.out.println("getName():          " + c.getName());
        System.out.println("getCanonicalName(): " + c.getCanonicalName());
        System.out.println("getSimpleName():    " + c.getSimpleName());
        System.out.println("toString():         " + c.toString());
        System.out.println();
    }

    private static void x(Runnable r) {
        showClass(r.getClass());
        showClass(java.lang.reflect.Array.newInstance(r.getClass(), 1).getClass()); // Obtains an array class of a lambda base type.
    }

    public static class NestedClass {}

    public class InnerClass {}

    public static void main(String[] args) {
        class LocalClass {}
        showClass(void.class);
        showClass(int.class);
        showClass(String.class);
        showClass(Runnable.class);
        showClass(SomeEnum.class);
        showClass(SomeAnnotation.class);
        showClass(int[].class);
        showClass(String[].class);
        showClass(NestedClass.class);
        showClass(InnerClass.class);
        showClass(LocalClass.class);
        showClass(LocalClass[].class);
        Object anonymous = new java.io.Serializable() {};
        showClass(anonymous.getClass());
        showClass(java.lang.reflect.Array.newInstance(anonymous.getClass(), 1).getClass()); // Obtains an array class of an anonymous base type.
        x(() -> {});
    }
}

enum SomeEnum {
   BLUE, YELLOW, RED;
}

@interface SomeAnnotation {}

这是完整的输出:

getName():          void
getCanonicalName(): void
getSimpleName():    void
toString():         void

getName():          int
getCanonicalName(): int
getSimpleName():    int
toString():         int

getName():          java.lang.String
getCanonicalName(): java.lang.String
getSimpleName():    String
toString():         class java.lang.String

getName():          java.lang.Runnable
getCanonicalName(): java.lang.Runnable
getSimpleName():    Runnable
toString():         interface java.lang.Runnable

getName():          com.example.SomeEnum
getCanonicalName(): com.example.SomeEnum
getSimpleName():    SomeEnum
toString():         class com.example.SomeEnum

getName():          com.example.SomeAnnotation
getCanonicalName(): com.example.SomeAnnotation
getSimpleName():    SomeAnnotation
toString():         interface com.example.SomeAnnotation

getName():          [I
getCanonicalName(): int[]
getSimpleName():    int[]
toString():         class [I

getName():          [Ljava.lang.String;
getCanonicalName(): java.lang.String[]
getSimpleName():    String[]
toString():         class [Ljava.lang.String;

getName():          com.example.TestClassNames$NestedClass
getCanonicalName(): com.example.TestClassNames.NestedClass
getSimpleName():    NestedClass
toString():         class com.example.TestClassNames$NestedClass

getName():          com.example.TestClassNames$InnerClass
getCanonicalName(): com.example.TestClassNames.InnerClass
getSimpleName():    InnerClass
toString():         class com.example.TestClassNames$InnerClass

getName():          com.example.TestClassNames$1LocalClass
getCanonicalName(): null
getSimpleName():    LocalClass
toString():         class com.example.TestClassNames$1LocalClass

getName():          [Lcom.example.TestClassNames$1LocalClass;
getCanonicalName(): null
getSimpleName():    LocalClass[]
toString():         class [Lcom.example.TestClassNames$1LocalClass;

getName():          com.example.TestClassNames$1
getCanonicalName(): null
getSimpleName():    
toString():         class com.example.TestClassNames$1

getName():          [Lcom.example.TestClassNames$1;
getCanonicalName(): null
getSimpleName():    []
toString():         class [Lcom.example.TestClassNames$1;

getName():          com.example.TestClassNames$$Lambda$1/1175962212
getCanonicalName(): com.example.TestClassNames$$Lambda$1/1175962212
getSimpleName():    TestClassNames$$Lambda$1/1175962212
toString():         class com.example.TestClassNames$$Lambda$1/1175962212

getName():          [Lcom.example.TestClassNames$$Lambda$1;
getCanonicalName(): com.example.TestClassNames$$Lambda$1/1175962212[]
getSimpleName():    TestClassNames$$Lambda$1/1175962212[]
toString():         class [Lcom.example.TestClassNames$$Lambda$1;

所以,这是规则。首先,让我们从基元类型开始,然后:void

  1. 如果类对象表示基元类型 或 ,则所有四个方法都只返回其名称。void

现在方法的规则:getName()

  1. 每个非 lambda 和非数组类或接口(即顶级、嵌套、内部、本地和匿名)都有一个名称(由 返回),该名称是包名称,后跟一个点(如果有包),后跟编译器生成的类文件的名称(后缀)。如果没有包,它只是类文件的名称。如果类是内部类、嵌套类、本地类或匿名类,则编译器应在其类文件名中至少生成一个类文件名。请注意,对于匿名类,类名将以美元符号结尾,后跟一个数字。getName().class$
  2. Lambda 类名通常是不可预测的,无论如何你都不应该关心它们。确切地说,它们的名称是封闭类的名称,后跟 ,后跟一个数字,后跟一个斜杠,后跟另一个数字。$$Lambda$
  3. 原语的类描述符是 for 、for 、for 、for 、for 、for 、for 和 for 。对于非数组类和接口,类描述符后跟 由 后跟 给出的内容。对于数组类,类描述符后跟组件类型的类描述符(它本身可能是另一个数组类)。ZbooleanBbyteSshortCcharIintJlongFfloatDdoubleLgetName();[
  4. 对于数组类,该方法返回其类描述符。此规则似乎仅适用于组件类型为 lambda 的数组类(这可能是一个错误),但希望这无论如何都无关紧要,因为即使存在组件类型为 lambda 的数组类也没有意义。getName()

现在,该方法:toString()

  1. 如果类实例表示接口(或注释,这是一种特殊类型的接口),则返回 .如果它是基元,则返回 .如果它是其他东西(类类型,即使它是一个非常奇怪的类型),它也会返回 .toString()"interface " + getName()getName()"class " + getName()

方法:getCanonicalName()

  1. 对于顶级类和接口,该方法仅返回该方法返回的内容。getCanonicalName()getName()
  2. 该方法返回匿名类或本地类以及这些类的数组类。getCanonicalName()null
  3. 对于内部和嵌套类和接口,该方法返回该方法将用点替换编译器引入的美元符号的内容。getCanonicalName()getName()
  4. 对于数组类,如果组件类型的规范名称为 。否则,它将返回组件类型的规范名称,后跟 。getCanonicalName()nullnull[]

方法:getSimpleName()

  1. 对于顶级类、嵌套类、内部类和本地类,返回写入源文件中的类的名称。getSimpleName()
  2. 对于匿名类,返回一个空的 .getSimpleName()String
  3. 对于 lambda 类,只返回不带包名称将返回的内容。这没有多大意义,对我来说看起来像一个错误,但是一开始调用 lambda 类是没有意义的。getSimpleName()getName()getSimpleName()
  4. 对于数组类,该方法返回组件类的简单名称,后跟 .这有一个有趣/奇怪的副作用,即组件类型为匿名类的数组类就像它们的简单名称一样。getSimpleName()[][]

分割线

网友回答:

如果您不确定某些内容,请尝试先编写测试。

我这样做了:

class ClassNameTest {
    public static void main(final String... arguments) {
        printNamesForClass(
            int.class,
            "int.class (primitive)");
        printNamesForClass(
            String.class,
            "String.class (ordinary class)");
        printNamesForClass(
            java.util.HashMap.SimpleEntry.class,
            "java.util.HashMap.SimpleEntry.class (nested class)");
        printNamesForClass(
            new java.io.Serializable(){}.getClass(),
            "new java.io.Serializable(){}.getClass() (anonymous inner class)");
    }

    private static void printNamesForClass(final Class<?> clazz, final String label) {
        System.out.println(label + ":");
        System.out.println("    getName():          " + clazz.getName());
        System.out.println("    getCanonicalName(): " + clazz.getCanonicalName());
        System.out.println("    getSimpleName():    " + clazz.getSimpleName());
        System.out.println("    getTypeName():      " + clazz.getTypeName()); // added in Java 8
        System.out.println();
    }
}

指纹:

int.class (primitive):
    getName():          int
    getCanonicalName(): int
    getSimpleName():    int
    getTypeName():      int

String.class (ordinary class):
    getName():          java.lang.String
    getCanonicalName(): java.lang.String
    getSimpleName():    String
    getTypeName():      java.lang.String

java.util.HashMap.SimpleEntry.class (nested class):
    getName():          java.util.AbstractMap$SimpleEntry
    getCanonicalName(): java.util.AbstractMap.SimpleEntry
    getSimpleName():    SimpleEntry
    getTypeName():      java.util.AbstractMap$SimpleEntry

new java.io.Serializable(){}.getClass() (anonymous inner class):
    getName():          ClassNameTest$1
    getCanonicalName(): null
    getSimpleName():    
    getTypeName():      ClassNameTest$1

最后一个块中有一个空条目,其中返回一个空字符串。getSimpleName

看到这个的结果是:

  • 该名称是用于动态加载类的名称,例如,使用默认值调用 。在某个范围内,所有类都有唯一的名称。Class.forNameClassLoaderClassLoader
  • 规范名称是将在导入语句中使用的名称。在或日志记录操作期间,它可能很有用。当编译器具有类路径的完整视图时,它会通过在编译时冲突完全限定的类和包名称来强制其中规范名称的唯一性。但是,JVM 必须接受此类名称冲突,因此规范名称不能唯一标识 .(事后看来,这个getter的更好名称是;但是这种方法可以追溯到JVM仅用于运行Java程序的时代。toStringjavacClassLoadergetJavaName
  • 简单名称松散地标识类,同样在 OR 日志记录操作期间可能很有用,但不能保证是唯一的。toString
  • 类型名称返回“此类型名称的信息字符串”,“就像:它纯粹是信息性的,没有合约价值”。(由Sir4ur0n撰写)toString

此外,您通常可以参考 Java 语言规范文档,了解这些类型的技术 Java API 详细信息:

  • 以下是关于此主题的 Java 11 规范:https://docs.oracle.com/javase/specs/jls/se11/html/jls-6.html#jls-6.7

Example 6.7-2.并分别过去和过去Example 6.7-2.Fully Qualified NamesFully Qualified Names v. Canonical Name

分割线

网友回答:

除了 Nick Holt 的观察之外,我还运行了几个数据类型案例:Array

//primitive Array
int demo[] = new int[5];
Class<? extends int[]> clzz = demo.getClass();
System.out.println(clzz.getName());
System.out.println(clzz.getCanonicalName());
System.out.println(clzz.getSimpleName());       

System.out.println();


//Object Array
Integer demo[] = new Integer[5]; 
Class<? extends Integer[]> clzz = demo.getClass();
System.out.println(clzz.getName());
System.out.println(clzz.getCanonicalName());
System.out.println(clzz.getSimpleName());

上面的代码片段打印:

[I
int[]
int[]

[Ljava.lang.Integer;
java.lang.Integer[]
Integer[]

模板简介:该模板名称为【在Java中,这些之间有什么区别:Object o1 = …. o1.getClass().getSimpleName();o1.getClass().getName();o1.getClass().getCanonicalName();】,大小是暂无信息,文档格式为.编程语言,推荐使用Sublime/Dreamweaver/HBuilder打开,作品中的图片,文字等数据均可修改,图片请在作品中选中图片替换即可,文字修改直接点击文字修改即可,您也可以新增或修改作品中的内容,该模板来自用户分享,如有侵权行为请联系网站客服处理。欢迎来懒人模板【Java】栏目查找您需要的精美模板。

相关搜索
  • 下载密码 lanrenmb
  • 下载次数 204次
  • 使用软件 Sublime/Dreamweaver/HBuilder
  • 文件格式 编程语言
  • 文件大小 暂无信息
  • 上传时间 02-26
  • 作者 网友投稿
  • 肖像权 人物画像及字体仅供参考
栏目分类 更多 >
热门推荐 更多 >
微信公众平台 微信文章 微信素材 企业网站 响应式 自适应 单页式简历模板 微信模板 微信图片 html5
您可能会喜欢的其他模板