Menambahkan kelas lokal, lambdas dan toString()
metode untuk melengkapi dua jawaban sebelumnya. Lebih lanjut, saya menambahkan array lambdas dan array kelas anonim (yang tidak masuk akal dalam praktiknya):
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 {}
Ini adalah hasil lengkapnya:
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;
Jadi, inilah aturannya. Pertama, mari kita mulai dengan tipe primitif dan void
:
- Jika objek kelas mewakili tipe primitif atau
void
, keempat metode hanya mengembalikan namanya.
Sekarang aturan untuk getName()
metode ini:
- Setiap kelas atau antarmuka non-lambda dan non-array (yaitu, tingkat atas, bersarang, dalam, lokal dan anonim) memiliki nama (yang dikembalikan oleh
getName()
) yaitu nama paket diikuti dengan titik (jika ada paket ), diikuti dengan nama file kelasnya seperti yang dihasilkan oleh kompiler (tanpa akhiran .class
). Jika tidak ada paket, itu hanya nama file kelas. Jika kelas adalah kelas dalam, bersarang, lokal atau anonim, kompiler harus menghasilkan setidaknya satu $
dalam nama file kelasnya. Perhatikan bahwa untuk kelas anonim, nama kelas akan diakhiri dengan tanda dolar diikuti dengan angka.
- Nama-nama kelas Lambda umumnya tidak dapat diprediksi, dan Anda seharusnya tidak peduli dengan mereka. Tepatnya, nama mereka adalah nama kelas yang dilampirkan, diikuti oleh
$$Lambda$
, diikuti oleh angka, diikuti oleh garis miring, diikuti oleh nomor lain.
- Deskripsi kelas primitif adalah
Z
untuk boolean
, B
untuk byte
, S
untuk short
, C
untuk char
, I
untuk int
, J
untuk long
, F
untuk float
dan D
untuk double
. Untuk kelas dan antarmuka non-array deskriptor kelas L
diikuti oleh apa yang diberikan oleh getName()
diikuti oleh ;
. Untuk kelas array, deskriptor kelas [
diikuti oleh deskriptor kelas dari tipe komponen (yang mungkin merupakan kelas array lain).
- Untuk kelas array, the
getName()
metode mengembalikan deskriptor kelasnya. Aturan ini tampaknya gagal hanya untuk kelas array yang tipe komponennya adalah lambda (yang mungkin merupakan bug), tetapi mudah-mudahan ini seharusnya tidak menjadi masalah juga karena tidak ada titik bahkan pada keberadaan kelas array yang tipe komponennya adalah lambda.
Sekarang, toString()
metodenya:
- Jika instance kelas mewakili antarmuka (atau anotasi, yang merupakan jenis antarmuka khusus),
toString()
hasilnya kembali "interface " + getName()
. Jika itu primitif, ia akan kembali dengan sederhana getName()
. Jika itu sesuatu yang lain (tipe kelas, bahkan jika itu cukup aneh), ia kembali "class " + getName()
.
The getCanonicalName()
Metode:
- Untuk kelas dan antarmuka tingkat atas,
getCanonicalName()
metode mengembalikan apa yang getName()
dikembalikan metode.
- Itu
getCanonicalName()
kembali metode null
untuk anonim atau kelas lokal dan untuk kelas array tersebut.
- Untuk kelas dan antarmuka bagian dalam dan bersarang,
getCanonicalName()
metode mengembalikan apagetName()
metode yang akan menggantikan tanda dolar yang diperkenalkan oleh kompiler oleh titik.
- Untuk kelas array,
getCanonicalName()
metode ini kembali null
jika nama kanonik tipe komponennya null
. Jika tidak, itu mengembalikan nama kanonik dari tipe komponen diikuti oleh []
.
The getSimpleName()
Metode:
- Untuk kelas tingkat atas, bersarang, dalam dan lokal, the
getSimpleName()
mengembalikan nama kelas seperti yang tertulis dalam file sumber.
- Untuk kelas anonim
getSimpleName()
mengembalikan sebuah kosongString
.
- Untuk kelas lambda,
getSimpleName()
hanya mengembalikan apa yang getName()
akan kembali tanpa nama paket. Ini tidak masuk akal dan terlihat seperti bug bagi saya, tetapi tidak ada gunanya memanggil getSimpleName()
kelas lambda untuk memulai.
- Untuk kelas array
getSimpleName()
metode mengembalikan nama kelas komponen sederhana diikuti oleh []
. Ini memiliki efek samping yang lucu / aneh yang dimiliki oleh kelas array yang jenis komponennya adalah kelas anonim []
.