การเพิ่มคลาสท้องถิ่น, lambdas และtoString()
เมธอดเพื่อทำสองคำตอบก่อนหน้าให้สมบูรณ์ นอกจากนี้ฉันยังเพิ่มอาร์เรย์ของ lambdas และอาร์เรย์ของคลาสที่ไม่ระบุชื่อ (ซึ่งไม่สมเหตุสมผลในทางปฏิบัติแม้ว่า):
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
:
- หากคลาสอ็อบเจ็กต์แสดงถึงชนิดดั้งเดิมหรือ
void
ทั้งสี่เมธอดจะส่งคืนชื่อ
ตอนนี้กฎสำหรับgetName()
วิธีการ:
- ทุกคลาสที่ไม่ใช่แลมบ์ดาและไม่ใช่อาเรย์หรืออินเทอร์เฟซ (เช่นระดับบนสุดซ้อนกันภายในท้องถิ่นและไม่ระบุชื่อ) มีชื่อ (ซึ่งถูกส่งกลับโดย
getName()
) นั่นคือชื่อแพคเกจตามด้วยจุด (ถ้ามีแพคเกจ ) ตามด้วยชื่อของไฟล์คลาสตามที่สร้างโดยคอมไพเลอร์ (โดยไม่มีคำต่อท้าย.class
) หากไม่มีแพ็คเกจมันเป็นเพียงชื่อของไฟล์คลาส ถ้าคลาสนั้นเป็นชั้นใน, ซ้อนกัน, ภายในหรือไม่ระบุชื่อคอมไพเลอร์ควรสร้างอย่างน้อยหนึ่ง$
ในชื่อไฟล์คลาส โปรดทราบว่าสำหรับคลาสที่ไม่ระบุชื่อชื่อคลาสจะลงท้ายด้วยเครื่องหมายดอลลาร์ตามด้วยตัวเลข
- โดยทั่วไปชื่อคลาสแลมบ์ดาไม่สามารถคาดเดาได้และคุณไม่ควรสนใจชื่อเหล่านั้น แน่นอนชื่อของพวกเขาคือชื่อของคลาสที่ปิดล้อมตามด้วย
$$Lambda$
ตามด้วยหมายเลขตามด้วยเครื่องหมายทับแล้วตามด้วยหมายเลขอื่น
- อธิบายระดับของวิทยาการที่มี
Z
สำหรับboolean
, B
สำหรับbyte
, S
สำหรับshort
, C
สำหรับchar
, I
สำหรับint
, J
สำหรับlong
, F
สำหรับfloat
และสำหรับD
double
สำหรับการเรียนไม่ใช่อาร์เรย์และอินเตอร์เฟซให้คำอธิบายถึงชั้นจะL
ตามมาด้วยสิ่งที่จะได้รับโดยตามด้วยgetName()
;
สำหรับคลาสอาเรย์คลาส descriptor นั้น[
ตามมาด้วยคลาส descriptor ของชนิดคอมโพเนนต์ (ซึ่งอาจเป็นคลาสอาเรย์ตัวอื่น)
- สำหรับคลาส Array
getName()
เมธอดจะส่งคืนคลาส descriptor กฎนี้ดูเหมือนว่าจะล้มเหลวเฉพาะสำหรับคลาสอาเรย์ที่มีประเภทองค์ประกอบเป็นแลมบ์ดา (ซึ่งอาจเป็นบั๊ก) แต่หวังว่าสิ่งนี้จะไม่สำคัญต่อไปเพราะไม่มีจุดใดเลยแม้แต่ในการมีอยู่ของคลาสอาเรย์
ตอนนี้toString()
วิธีการ:
- ถ้าเช่นชั้นหมายถึงอินเตอร์เฟซ (หรือคำอธิบายประกอบซึ่งเป็นชนิดพิเศษของอินเตอร์เฟซ) ซึ่งเป็นผลตอบแทน
toString()
ถ้าเป็นแบบดั้งเดิมก็จะส่งกลับเพียง"interface " + getName()
getName()
ถ้ามันเป็นอย่างอื่น (ประเภทชั้นถึงแม้ว่ามันจะเป็นที่แปลกสวยหนึ่ง) "class " + getName()
ก็จะส่งกลับ
getCanonicalName()
วิธีการ:
- สำหรับคลาสและอินเตอร์เฟสระดับสูงสุด
getCanonicalName()
เมธอดจะส่งคืนสิ่งที่getName()
เมธอดส่งคืน
getCanonicalName()
วิธีการผลตอบแทนที่null
ไม่ระบุชื่อหรือเรียนในท้องถิ่นและสำหรับการเรียนอาร์เรย์ของคนเหล่านั้น
- สำหรับคลาสและอินเทอร์เฟซภายในและอินเทอร์เฟซ
getCanonicalName()
วิธีการส่งกลับสิ่งที่getName()
วิธีการจะแทนที่สัญญาณดอลลาร์แนะนำคอมไพเลอร์โดยจุด
- สำหรับการเรียนอาร์เรย์ที่
getCanonicalName()
วิธีการส่งกลับถ้าชื่อบัญญัติของชนิดเป็นส่วนประกอบnull
มิฉะนั้นก็จะส่งกลับชื่อบัญญัติประเภทองค์ประกอบตามnull
[]
getSimpleName()
วิธีการ:
- สำหรับคลาสระดับบนสุดซ้อนกันภายในและภายใน
getSimpleName()
จะส่งคืนชื่อของคลาสตามที่เขียนในไฟล์ต้นฉบับ
- สำหรับการเรียนที่ไม่ระบุชื่อส่งกลับว่างเปล่า
getSimpleName()
String
- สำหรับคลาสแลมบ์ดา
getSimpleName()
เพียงแค่คืนค่าที่getName()
จะให้โดยไม่มีชื่อแพ็กเกจ สิ่งนี้ไม่สมเหตุสมผลและดูเหมือนว่าเป็นข้อบกพร่องสำหรับฉัน แต่ไม่มีจุดเริ่มต้นในการเรียกgetSimpleName()
คลาสแลมบ์ดา
- สำหรับการเรียนอาร์เรย์วิธีการผลตอบแทนที่เรียบง่ายของชื่อชั้นองค์ประกอบตามมาด้วย
getSimpleName()
[]
สิ่งนี้มีผลข้างเคียงตลก / แปลก ๆ ที่คลาสอาเรย์ที่มีชนิดส่วนประกอบเป็นคลาสแบบไม่ระบุชื่อมี[]
ชื่อแบบง่าย ๆ