คลาสที่ยกย่องในภาษา Java


96

คลาสบางคลาสใน Java API มาตรฐานได้รับการปฏิบัติที่แตกต่างจากคลาสอื่นเล็กน้อย ฉันกำลังพูดถึงคลาสเหล่านั้นที่ไม่สามารถใช้งานได้หากไม่มีการสนับสนุนพิเศษจากคอมไพเลอร์และ / หรือ JVM

สิ่งที่ฉันคิดขึ้นมาทันทีคือ:

  • Object (ชัดเจน) เหมือนอย่างอื่นไม่มีซุปเปอร์คลาส
  • String เนื่องจากภาษามีการสนับสนุนพิเศษสำหรับตัวดำเนินการ +
  • Thread เนื่องจากมีเมธอด start () ที่มีมนต์ขลังนี้แม้ว่าจะไม่มีคำสั่ง bytecode ที่ "แยก" การดำเนินการ

ฉันคิดว่าทุกชั้นเรียนเช่นนี้มีไม่ทางใดก็ทางหนึ่งที่กล่าวถึงใน JLS ช่วยแก้ให้ด้วยนะถ้าฉันผิด.

แล้วมีคลาสอะไรอีกบ้าง? มีรายการ "คลาสที่ได้รับการยกย่อง" ทั้งหมดในภาษา Java หรือไม่


2
Genericsเกือบพอดี แต่ไม่มาก พวกเขาถูกนำไปใช้โดยใช้เคล็ดลับคอมไพเลอร์ แต่ไม่ได้แยกเป็นคลาสเดียว
Bill the Lizard

2
พวกเขาทั้งหมดเป็นประเภทแสดงความเคารพ ;-)
starblue

1
"thread.start" มีมนต์ขลังหรือไม่? แน่นอนว่ามันเป็นเพียงโค้ดเนทีฟที่เรียกให้ทำสิ่งนี้
jcoder

ความคิดนั้นทำให้ฉันรู้สึกเหมือนกัน บางที JNI เพียงอย่างเดียวก็เพียงพอที่จะใช้คลาส Thread ฉันคิดว่าถ้าฉันจะลองทำสิ่งนี้ฉันจะใช้ API เธรดระดับ OS บางตัวแยกการดำเนินการในการใช้งานเมธอด start () เรียกใช้วิธีการ run () ในเธรดที่ถูกแยกออกและส่งคืน แต่เธรดระบบปฏิบัติการของฉันก็ยังคงทำงานต่อไป จะทำงานได้อย่างราบรื่นพร้อมกับเธรดที่สร้างโดย JVM หรือไม่? และให้เกียรติกับโมเดลหน่วยความจำ JLS เป็นต้น?
aioobe

2
ตามข้อกำหนดวิธีเดียวในการสร้างเธรดคือจากคลาสเธรด ( java.sun.com/docs/books/jvms/second_edition/html/… ) แน่นอนว่ามันขึ้นอยู่กับการสื่อสารระดับไร้เดียงสากับ JVM แต่ถ้าคุณทำ JNI ของคุณเองคุณอาจเริ่มเธรด แต่คุณจะไม่ได้รับ JVM เพื่อเข้าใจสิ่งที่คุณกำลังทำอยู่ (ล็อคโมเดลหน่วยความจำ ฯลฯ ). เธรดมีสิทธิพิเศษที่ข้อมูลจำเพาะจะกำหนดสิทธิพิเศษให้กับเธรด - วิธีเดียวในการเริ่มเธรด
Yishai

คำตอบ:


35

มีคำตอบที่แตกต่างกันมากมายดังนั้นฉันจึงคิดว่าการรวบรวมคำตอบทั้งหมดจะมีประโยชน์ (และเพิ่มบางส่วน):

ชั้นเรียน

  • คลาสAutoBoxing - คอมไพเลอร์อนุญาตเฉพาะคลาสเฉพาะเท่านั้น
  • Class - มีตัวอักษรของตัวเอง (เช่น int.class เช่น) ฉันจะเพิ่มการพิมพ์ทั่วไปโดยไม่ต้องสร้างอินสแตนซ์ใหม่
  • สตริง - ด้วยตัวดำเนินการ + ที่มากเกินไปและการสนับสนุนตัวอักษร
  • Enum - คลาสเดียวที่สามารถใช้ในคำสั่ง switch (ในไม่ช้าก็จะได้รับสิทธิ์ให้กับ String เช่นกัน) มันทำสิ่งอื่น ๆ เช่นกัน (การสร้างวิธีการแบบคงที่โดยอัตโนมัติการจัดการการทำให้เป็นอนุกรม ฯลฯ ) แต่สิ่งเหล่านี้สามารถทำได้ในทางทฤษฎีด้วยรหัส - มันเป็นเพียงสำเร็จรูปจำนวนมากและข้อ จำกัด บางอย่างไม่สามารถบังคับใช้ในคลาสย่อยได้ (เช่น กฎคลาสย่อยพิเศษ) แต่สิ่งที่คุณไม่สามารถทำได้หากไม่มีสถานะส่วนตัวของ enum จะรวมไว้ในคำสั่ง switch
  • Object - รูทของออบเจ็กต์ทั้งหมด (และฉันจะเพิ่มโคลนและวิธีการสรุปไม่ใช่สิ่งที่คุณสามารถนำไปใช้ได้)
  • ข้อมูลอ้างอิง : WeakReference, SoftReference, PhantomReference
  • เธรด - ภาษาไม่ได้ให้คำสั่งเฉพาะแก่คุณในการเริ่มเธรด แต่จะใช้กับเมธอด start () อย่างน่าอัศจรรย์
  • Throwable - รูทของคลาสทั้งหมดที่สามารถทำงานร่วมกับการโยนการขว้างและการจับรวมทั้งความเข้าใจของคอมไพเลอร์เกี่ยวกับ Exception vs. RuntimeException และ Error
  • NullPointerExceptionและข้อยกเว้นอื่น ๆ เช่น ArrayIndexOutOfBounds ซึ่งสามารถส่งโดยคำสั่ง bytecode อื่นที่ไม่ใช่ที่

อินเทอร์เฟซ

  • ทำซ้ำได้ - อินเทอร์เฟซเดียวที่สามารถใช้ในการปรับปรุงสำหรับลูป

คำกล่าวที่น่ายกย่องไปที่:

  • java.lang.reflect Array - การสร้างอาร์เรย์ใหม่ตามที่กำหนดโดยคลาสออบเจ็กต์จะไม่สามารถทำได้
  • คำอธิบายประกอบเป็นคุณลักษณะภาษาพิเศษที่ทำงานเหมือนอินเทอร์เฟซที่รันไทม์ แน่นอนคุณไม่สามารถกำหนดอินเทอร์เฟซ Annotation อื่นได้เช่นเดียวกับที่คุณไม่สามารถกำหนดการแทนที่ Object ได้ อย่างไรก็ตามคุณสามารถใช้ฟังก์ชันการทำงานทั้งหมดและมีวิธีอื่นในการดึงข้อมูล (และแผ่นสำเร็จรูปทั้งหมด) แทนที่จะเป็นภาพสะท้อน ในความเป็นจริงมีการใช้งานตาม XML และแท็ก javadoc จำนวนมากก่อนที่จะนำคำอธิบายประกอบ
  • ClassLoader - แน่นอนว่ามีความสัมพันธ์ที่เป็นสิทธิพิเศษกับ JVM เนื่องจากไม่มีวิธีภาษาในการโหลดคลาสแม้ว่าจะมีวิธี bytecode ก็ตามดังนั้นจึงเป็นเหมือน Array ในลักษณะนั้น นอกจากนี้ยังมีสิทธิพิเศษในการถูกเรียกกลับโดย JVM แม้ว่าจะเป็นรายละเอียดการดำเนินการก็ตาม
  • ต่อเนื่องได้ - คุณสามารถใช้ฟังก์ชันผ่านการสะท้อนกลับได้ แต่มีคีย์เวิร์ดที่เป็นเอกสิทธิ์ของตัวเองและคุณจะใช้เวลาส่วนใหญ่ในการทำความคุ้นเคยกับ SecurityManager ในบางสถานการณ์

หมายเหตุ: ฉันทิ้งสิ่งที่ให้ JNI (เช่น IO) ไว้ในรายการเพราะคุณสามารถใช้การโทร JNI ของคุณเองได้ตลอดเวลาหากคุณมีความโน้มเอียง อย่างไรก็ตามการเรียกแบบเนทีฟที่โต้ตอบกับ JVM ในรูปแบบสิทธิพิเศษนั้นแตกต่างกัน

อาร์เรย์เป็นที่ถกเถียงกันได้ - พวกมันสืบทอด Object มีลำดับชั้นที่เข้าใจได้ (Object [] คือ supertype ของ String []) แต่เป็นคุณลักษณะของภาษาไม่ใช่คลาสที่กำหนดด้วยตัวมันเอง


@ Donal จริงมากฉันกำลังคิดถึงคำอธิบายประกอบแบบรันไทม์ แต่คำอธิบายประกอบระดับซอร์สถูกทำด้วยวิธีนั้น (xdoclet สะดุดตามากที่สุดหรือแม้แต่ใน core java ที่มี @deprecated)
Yishai

ฉันเพิ่งต่อสู้กับรหัสหนาทึบที่เขียนด้วยการประมวลผล xdoclet จากนั้นแปลงเป็นคำอธิบายประกอบ โอ้ฉันชอบคำอธิบายประกอบมากกว่าอย่างไร (แม้ว่าจะมีคาถามาเวนที่เหมาะสม แต่เอฟเฟกต์สุทธิก็เหมือนกัน)
Donal Fellows

@ KK_07k11A0585 คอลเลกชันเป็น API มาตรฐานที่ทุกคนสามารถสร้างขึ้นด้วยวิธีอื่น (อันที่จริงมีการใช้งานทางเลือกอื่นที่มุ่งเน้นไปที่ยุคดั้งเดิมเช่นเดียวกับโครงการ Google ที่มีชื่อเสียงมากซึ่งช่วยเพิ่มประสิทธิภาพ) สิ่งเดียวที่พวกเขาได้รับซึ่งพิเศษคือ Iterable ซึ่งกล่าวถึงในคำตอบ พวกเขาเป็นขนมปังและเนยของการเขียนโปรแกรม Java แน่นอน แต่เป็นเพียงชั้นเรียนปกติไม่มีสิทธิพิเศษ
Yishai

@Yishai ในขณะที่พัฒนาแอปพลิเคชันใด ๆ สิ่งสำคัญที่ให้ความสำคัญคือการจัดการข้อมูล เราทุกคนสามารถทำงานได้หลายวิธี แต่วิธีที่ดีที่สุดคือวิธีที่ใช้หน่วยความจำน้อยกว่าและใช้การอ้างอิงที่ไม่จำเป็นน้อยกว่า ด้วยการใช้ Collections เราสามารถจัดเรียงค้นหาและเปรียบเทียบข้อมูลจำนวนมากซึ่งมีอัลกอริทึมที่กำหนดไว้ล่วงหน้าเช่น Binary Search, Merge Sort เป็นต้นนอกจากนี้ยังมี Comparator และ Comparable Interfaces เพื่อปรับแต่งเทคนิคของเรา คลาสคอลเลกชันอาจไม่ใช่คลาสที่ดีที่สุดใน java แต่เป็นคลาสที่มีคุณภาพที่น่ายกย่องอย่างไม่ต้องสงสัย
KK_07k11A0585

1
เกี่ยวกับอะไรSecurityManager? หรืออะไรที่เกี่ยวข้องกับการสะท้อนหรือการทำให้เป็นอนุกรม?
Antimony

19

Class, แน่นอน. มันมีตัวอักษรของตัวเอง (ความแตกต่างที่มันใช้ร่วมกับStringBTW) และเป็นจุดเริ่มต้นของเวทมนตร์สะท้อนทั้งหมดนั้น


อ่าจุดดี แล้วตัวอย่างของตัวอักษรคลาสคืออะไร? คุณหมายถึง MyClass.class หรือไม่
aioobe

4
@aioobe: เป๊ะ. โปรดทราบว่าคุณมี int.class, char.class และอื่น ๆ เช่นกัน
Michael Borgwardt


12
  1. Enum. คุณไม่ได้รับอนุญาตให้ซับคลาส แต่คอมไพเลอร์สามารถทำได้
  2. หลายสิ่งภายใต้ java.util.concurrent สามารถใช้งานได้โดยไม่ต้องรองรับ JVM แต่จะมีประสิทธิภาพน้อยกว่ามาก

1
คุณสามารถ enums คลาสย่อยแบบไม่ระบุตัวตน (ซึ่งเป็นฐานของรูปแบบผู้เยี่ยมชมโดยนัยสำหรับค่า enums) แต่ใช่คุณไม่สามารถ subclass enum ได้อย่างสมบูรณ์ ;-)
Thierry

11

ทั้งหมดของชั้นเรียนจำนวนมีนิด ๆ หน่อย ๆ ของมายากลในรูปแบบของAutoboxing


คุณหมายถึงคลาสที่ห่อหุ้มสิ่งดั้งเดิม - ซึ่งรวมถึงบูลีนและอักขระด้วย แต่ไม่รวม BigInteger
emory

1
@emory: ใช่แค่คลาส Wrapper ดั้งเดิม ขออภัยที่ไม่รวม BigInteger
Bill the Lizard

10

เนื่องจากมีการกล่าวถึงคลาสที่สำคัญฉันจะพูดถึงอินเทอร์เฟซบางส่วน:

Iterableอินเตอร์เฟซ (ตั้งแต่ 1.5) - มันช่วยให้วัตถุที่จะมีส่วนร่วมในวง foreach:

Iterable<Foo> iterable = ...;
for (Foo foo : iterable) {

}

Serializableอินเตอร์เฟซที่มีความหมายมากเป็นพิเศษแตกต่างจากมาตรฐานการเชื่อมต่อ คุณสามารถกำหนดวิธีการที่จะนำมาพิจารณาแม้ว่าจะไม่ได้กำหนดไว้ในอินเทอร์เฟซ (เช่นreadResolve()) transientคำหลักที่เป็นองค์ประกอบของภาษาที่มีผลต่อพฤติกรรมของSerializableimplementors


จริงอยู่พวกเขาเป็นอินเทอร์เฟซดังนั้นจึงไม่จำเป็นต้องมีการใช้งาน "พิเศษ" ต่อดู (คล้ายกับ Throwable)
aioobe

ต่อเนื่องได้จริงต้องใช้งานพิเศษ เป็นอินเทอร์เฟซที่คุณคาดว่าจะมีสองวิธี (ฉันลืมชื่อ ... ฉันสามารถ google ได้ ... ) แต่ไม่จำเป็นหรือกำหนดไว้ในโครงร่างอินเทอร์เฟซมาตรฐาน
corsiKa

@glowcoder: อย่างไรก็ตามครั้งหนึ่งอาจโต้แย้งว่าความพิเศษทั้งหมดของ Serializable ไม่เกี่ยวข้องกับภาษา Java เฉพาะกับการใช้งาน ObjectOutputStream และ ObjectInputStream
Michael Borgwardt

5
@Michael Borgwardt มี - transientคำหลัก
Bozho

1
ฉันไม่คิดอย่างนั้น - Comparableไม่ได้มีส่วนร่วมอะไรภายใน คุณสามารถเขียนNewComparableและเขียนใหม่ได้อย่างง่ายดายNewArrays.sort(..)ด้วยฟังก์ชันเดียวกัน
Bozho

6
  1. Throwable , RuntimeException, Error AssertionError
  2. การอ้างอิง WeakReference, SoftReference, PhantomReference
  3. Enum
  4. คำอธิบายประกอบ

รายการที่ดี +1, Annotation เป็นอินเทอร์เฟซและไม่มีการใช้งาน
aioobe

1
คำอธิบายประกอบได้รับการปฏิบัติโดยคอมไพลเลอร์แตกต่างจากอินเทอร์เฟซปกติ เช่นเดียวกับ enum พวกเขาทั้งหมดขยายคำอธิบายประกอบและคอมไพเลอร์ก็ทำเช่นนั้นโดยอัตโนมัติ จาก JavaDoc ของ Annotation: อินเทอร์เฟซทั่วไปที่ขยายโดยประเภทคำอธิบายประกอบทั้งหมด โปรดทราบว่าอินเทอร์เฟซที่ขยายด้วยตนเองนี้ไม่ได้กำหนดประเภทคำอธิบายประกอบ โปรดทราบว่าอินเทอร์เฟซนี้ไม่ได้กำหนดประเภทคำอธิบายประกอบเอง ดังนั้นคุณจึงไม่สามารถสร้างคำอธิบายประกอบโดยใช้ไวยากรณ์ปกติได้พวกเขาจำเป็นต้องเปลี่ยนคอมไพเลอร์เพื่อเพิ่ม
Andrei Fierbinteanu



2

ไม่แน่ใจเกี่ยวกับเรื่องนี้ แต่ฉันไม่สามารถคิดวิธีที่จะใช้อ็อบเจ็กต์ IO ด้วยตนเอง


คุณพูดถูกพวกเขาไม่สามารถนำไปใช้ใน Java บริสุทธิ์ได้ ต้องดำเนินการผ่าน JNI (เช่นเดียวกับคลาสอื่น ๆ ที่ต้องทำการเรียกระบบ) อย่างไรก็ตามนอกเหนือจากนั้นพวกเขาไม่ต้องการการสนับสนุนพิเศษจากคอมไพเลอร์หรือ jvm
aioobe

2

มีเวทมนตร์บางอย่างในSystemชั้นเรียน

System.arraycopy เป็นการเชื่อมต่อกับโค้ดเนทีฟ

public static native void arraycopy(Object array1, int start1, 
  Object array2, int start2, int length);

แต่...

/**
 * Private version of the arraycopy method used by the jit
 * for reference arraycopies
 */
private static void arraycopy(Object[] A1, int offset1,
  Object[] A2, int offset2, int length) {
   ...
}

1
เฮ้คุณหมายถึงอะไรในส่วนที่สองของคำตอบ?
Pacerier

1

เนื่องจากมีการกล่าวถึงการจัดการการยืนยันแบบพิเศษ ต่อไปนี้เป็นประเภทข้อยกเว้นเพิ่มเติมซึ่งมีการดูแลเป็นพิเศษโดย jvm:

  • NullPointerException
  • ArithmeticException
  • StackOverflowException
  • OutOfMemoryErrors ทุกชนิด
  • ...

ข้อยกเว้นไม่พิเศษ แต่ jvm ใช้ในกรณีพิเศษดังนั้นคุณจึงไม่สามารถใช้งานได้ด้วยตนเองโดยไม่ต้องเขียน jvm ของคุณเอง ฉันแน่ใจว่ามีข้อยกเว้นพิเศษมากกว่านี้


0

คลาสเหล่านั้นส่วนใหญ่ไม่ได้ใช้งานด้วยความช่วยเหลือ 'พิเศษ' จากคอมไพเลอร์หรือ JVM ออบเจ็กต์จะลงทะเบียนเนทีฟบางตัวที่โผล่รอบโครงสร้าง JVM ภายใน แต่คุณสามารถทำได้สำหรับคลาสของคุณเองเช่นกัน (ฉันยอมรับว่าสิ่งนี้อยู่ภายใต้ความหมาย "การเรียกเนทีฟที่กำหนดไว้ใน JVM" ถือได้ว่าเป็นการสนับสนุน JVM แบบพิเศษ)

อะไร / คือ / พิเศษคือพฤติกรรมของคำสั่ง 'ใหม่' และ 'โยน' ในการเริ่มต้นโครงสร้างภายในเหล่านี้

คำอธิบายประกอบและตัวเลขค่อนข้างนอกลู่นอกทาง


4
aioobe หมายถึงคลาสที่คุณไม่สามารถใช้งานได้ด้วยตัวเองเนื่องจากมีการสนับสนุนแบบพิเศษ คุณไม่สามารถสร้างคลาส Object ของคุณเองเป็นรูทของระบบ type โดยไม่ต้องสืบทอดรูปแบบ java.lang.Object ออบเจ็กต์ได้รับการสนับสนุนพิเศษจากทั้งคอมไพเลอร์และ jvm เพื่อให้แน่ใจว่าเป็นคลาสรูท การโทรภายในไม่เพียงพอที่จะแก้ไขปัญหานี้
josefx
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.