当前位置: 首页 > 知识库问答 >
问题:

Java类中的规范名、简单名和类名有什么区别?

东方灵均
2023-03-14

在Java,这些有什么区别:

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

我已经检查了Javadoc多次,但这始终不能很好地解释它。我还运行了一个测试,但这并没有反映出这些方法的调用方式背后的任何真正意义。

共有3个答案

凌智
2023-03-14

除了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[]
罗法
2023-03-14

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

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()方法的规则:

现在,toString()方法:

GetCanonicalName()方法:

getSimplename()方法:

勾渝
2023-03-14

如果你不确定什么,试着先写一个测试。

我是这样做的:

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.ForName调用ClassLoader。在某个类加载器的范围内,所有类都有唯一的名称。
  • 规范名称是将在import语句中使用的名称。它在toString或日志记录操作期间可能很有用。当javac编译器具有类路径的完整视图时,它通过在编译时冲突完全限定的类和包名称来强制其内部规范名称的唯一性。但是,JVM必须接受这种名称冲突,因此规范名称不能唯一标识类加载器中的类。(事后看来,这个getter的更好名称应该是getJavaName;但是这个方法可以追溯到JVM仅用于运行Java程序的时候。)
  • 简单名称不严格地标识类,在ToString日志记录操作期间也可能有用,但不保证唯一。
  • 类型名称返回“该类型名称的信息字符串”,“It's liketoString:它纯粹是信息性的,没有约定值”。(如sir4ur0n所写)
 类似资料:
  • 问题内容: 在Java中,这些之间有什么区别: 我已经多次检查过Javadoc,但这从来不能很好地解释它。我也进行了测试,但没有反映出调用这些方法背后的任何实际含义。 问题答案: 如果不确定某件事,请尝试先编写测试。 我这样做: 印刷品: 最后一个块中有一个空条目,其中返回一个空字符串。 结果是: 该 名称 是您愿意使用动态加载与类,例如,调用的名称与默认。在一定范围内,所有类都有唯一的名称。 该

  • 我是java新手。当我试图在5分钟内学会Maven时,我发现这个命令 工作方式与 这让我发疯,因为第二个命令中的最后一个参数实际上是一个路径。java类名中的“.”和“/”有什么区别? 我已经查了一些文章,但仍然不明白。

  • 问题内容: 直接使用和直接使用父类名称之间有区别吗?例如: 是否有内部之间的差异和? 问题答案: 在 这种情况下 不是。但是 通常 ,尤其是当您使用 多重继承时 ,按照文档中指定 的 方法 委托给 方法解析顺序(MRO)中 的下一个对象 : 返回将方法调用委托给类型的父级或同级类的 代理对象 。这对于访问已在类中重写的继承方法很有用。搜索顺序与所使用的顺序相同,只是类型本身被跳过。 类型的 属性列

  • 输出:类名:包。名称在这里B 有人能告诉我为什么匿名类类型在getClass()方法中给出封闭类吗?这导致了问题的出现。对象C上的equals()始终失败。我的理解是,由于getClass提供了封闭类名,所以永远不会调用重写的equals?

  • 1、模块 模块尽量使用小写命名,首字母保持小写,尽量不要用下划线(除非多个单词,且数量不多的情况) # 正确的模块名 import decoder import html_parser # 不推荐的模块名 import Decoder 2、类名 类名使用驼峰(CamelCase)命名风格,首字母大写,私有类可用一个下划线开头 class Farm(): pass class Anim

  • 我可以在命令行中为两个签名者签名Apk吗?