Não confie em class.getSimpleName () ou class.getCanonicalName ()

Construir código que obtém universalmente o nome da classe de um objeto pode ter algumas armadilhas inesperadas em Java. Você nunca deve confiar class.getSimpleName()ou class.getCanonicalName()fornecer algo significativo se seu código puder receber objetos arbitrários de qualquer classe. Especialmente para objetos criados anonimamente, eles estarão vazios ou nulos.

Para dar um exemplo, este script irá gerar a saída abaixo dele:

import java.util.function.BiConsumer;
import java.util.function.Consumer;

import static java.lang.String.format;

/**
* Demo of some common pitfalls with class.getSimpleName() and class.getCanonicalName().

* @author David Klotz

*/

public class MyClassNames {

private static class StaticInnerClass {}
private class InnerClass {}

private static void logClassName(String prefix, Class<?> clazz) {
System.out.println(format("%s:n Simple:t '%s'n Name :t '%s'n Canonical:t '%s'n Type name:t '%s'nn", prefix, clazz.getSimpleName(), clazz.getName(), clazz.getCanonicalName(), clazz.getTypeName()));
}

public static void main(String[] args) {
Runnable anonymous = new Runnable() {
@Override
public void run() {

}
};

Runnable someLambda = () -> {};
Consumer<String> someOtherLambda = s -> {};
BiConsumer<String, Class<?>> methodReference = MyClassNames::logClassName;

logClassName
("Normal class", MyClassNames.class);
logClassName
("Static inner class", MyClassNames.StaticInnerClass.class);
logClassName
("Inner class", MyClassNames.InnerClass.class);
logClassName
("Anonymous class", anonymous.getClass());
logClassName
("Lambda runnable class", someLambda.getClass());
logClassName
("Lambda consumer class", someOtherLambda.getClass());
logClassName
("Method reference class", methodReference.getClass());
}
}

Resultado:

Normal class:
Simple: 'MyClassNames'
Name : 'com.example.MyClassNames'
Canonical: 'com.example.MyClassNames'
Type name: 'com.example.MyClassNames'


Static inner class:
Simple: 'StaticInnerClass'
Name : 'com.example.MyClassNames$StaticInnerClass'
Canonical: 'com.example.MyClassNames.StaticInnerClass'
Type name: 'com.example.MyClassNames$StaticInnerClass'


Inner class:
Simple: 'InnerClass'
Name : 'com.example.MyClassNames$InnerClass'
Canonical: 'com.example.MyClassNames.InnerClass'
Type name: 'com.example.MyClassNames$InnerClass'


Anonymous class:
Simple: ''
Name : 'com.example.MyClassNames$1'
Canonical: 'null'
Type name: 'com.example.MyClassNames$1'


Lambda runnable class:
Simple: 'MyClassNames$$Lambda$1/110992469'
Name : 'com.example.MyClassNames$$Lambda$1/110992469'
Canonical: 'com.example.MyClassNames$$Lambda$1/110992469'
Type name: 'com.example.MyClassNames$$Lambda$1/110992469'


Lambda consumer class:
Simple: 'MyClassNames$$Lambda$2/1638172114'
Name : 'com.example.MyClassNames$$Lambda$2/1638172114'
Canonical: 'com.example.MyClassNames$$Lambda$2/1638172114'
Type name: 'com.example.MyClassNames$$Lambda$2/1638172114'


Method reference class:
Simple: 'MyClassNames$$Lambda$3/1651945012'
Name : 'com.example.MyClassNames$$Lambda$3/1651945012'
Canonical: 'com.example.MyClassNames$$Lambda$3/1651945012'
Type name: 'com.example.MyClassNames$$Lambda$3/1651945012'