Thêm các lớp địa phương, lambdas và toString()
phương pháp để hoàn thành hai câu trả lời trước. Hơn nữa, tôi thêm các mảng lambdas và mảng các lớp ẩn danh (mặc dù không có ý nghĩa gì trong thực tế):
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 {}
Đây là đầu ra đầy đủ:
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;
Vì vậy, đây là các quy tắc. Đầu tiên, hãy bắt đầu với các kiểu nguyên thủy và void
:
- Nếu đối tượng lớp đại diện cho một kiểu nguyên thủy hoặc
void
, tất cả bốn phương thức chỉ đơn giản trả về tên của nó.
Bây giờ các quy tắc cho getName()
phương thức:
- Mỗi lớp hoặc giao diện không phải là lambda và không phải mảng (nghĩa là cấp cao nhất, lồng nhau, bên trong, cục bộ và ẩn danh) có một tên (được trả về bởi
getName()
) đó là tên gói theo sau là dấu chấm (nếu có gói ), theo sau là tên của tệp lớp của nó được tạo bởi trình biên dịch (không có hậu tố .class
). Nếu không có gói, nó chỉ đơn giản là tên của tệp lớp. Nếu lớp là một lớp bên trong, lồng nhau, cục bộ hoặc ẩn danh, trình biên dịch sẽ tạo ra ít nhất một $
trong tên tệp lớp của nó. Lưu ý rằng đối với các lớp ẩn danh, tên lớp sẽ kết thúc bằng ký hiệu đô la theo sau là một số.
- Tên lớp Lambda thường không thể đoán trước và dù sao bạn cũng không nên quan tâm đến chúng. Chính xác, tên của họ là tên của lớp kèm theo, theo sau là
$$Lambda$
, theo sau là một số, theo sau là dấu gạch chéo, theo sau là một số khác.
- Các mô tả lớp của nguyên thủy là
Z
cho boolean
, B
cho byte
, S
cho short
, C
cho char
, I
cho int
, J
cho long
, F
cho float
và D
cho double
. Đối với các lớp và giao diện không phải là mảng, bộ mô tả lớp được L
theo sau bởi những gì được cho bởi getName()
theo sau bởi;
. Đối với các lớp mảng, bộ mô tả lớp được [
theo sau bởi bộ mô tả lớp của loại thành phần (có thể chính nó là một lớp mảng khác).
- Đối với các lớp mảng,
getName()
phương thức trả về mô tả lớp của nó. Quy tắc này dường như chỉ thất bại đối với các lớp mảng có loại thành phần là lambda (có thể là lỗi), nhưng hy vọng điều này không thành vấn đề vì dù sao cũng không có sự tồn tại của các lớp mảng có loại thành phần là lambda.
Bây giờ, toString()
phương thức:
- Nếu cá thể lớp đại diện cho một giao diện (hoặc một chú thích, là một loại giao diện đặc biệt), thì
toString()
trả về "interface " + getName()
. Nếu nó là một nguyên thủy, nó trở lại đơn giản getName()
. Nếu nó là một cái gì đó khác (một loại lớp, ngay cả khi nó là một loại khá kỳ lạ), nó sẽ trả về "class " + getName()
.
Các getCanonicalName()
phương pháp:
- Đối với các lớp và giao diện cấp cao nhất,
getCanonicalName()
phương thức trả về đúng những gì getName()
phương thức trả về.
- Các
getCanonicalName()
trở về phương pháp null
cho vô danh hoặc các lớp học tại địa phương và cho các lớp mảng của những người.
- Đối với các lớp và giao diện bên trong và lồng nhau,
getCanonicalName()
phương thức trả về những gìgetName()
phương thức sẽ thay thế các ký hiệu đô la do trình biên dịch giới thiệu bằng dấu chấm.
- Đối với các lớp mảng,
getCanonicalName()
phương thức trả về null
nếu tên chính tắc của kiểu thành phần là null
. Mặt khác, nó trả về tên chính tắc của loại thành phần theo sau []
.
Các getSimpleName()
phương pháp:
- Đối với các lớp cấp cao nhất, lồng nhau, bên trong và cục bộ,
getSimpleName()
trả về tên của lớp như được ghi trong tệp nguồn.
- Đối với các lớp ẩn danh,
getSimpleName()
trả về một khoảng trốngString
.
- Đối với các lớp lambda,
getSimpleName()
chỉ trả về những gì getName()
sẽ trả về mà không có tên gói. Điều này không có nhiều ý nghĩa và có vẻ như là một lỗi đối với tôi, nhưng không có lý do gì để gọigetSimpleName()
một lớp lambda để bắt đầu.
- Đối với các lớp mảng,
getSimpleName()
phương thức trả về tên đơn giản của lớp thành phần theo sau []
. Điều này có tác dụng phụ buồn cười / kỳ lạ là các lớp mảng có loại thành phần là một lớp ẩn danh có []
tên đơn giản như chúng.