ทำไม Java อนุญาตให้เรารวบรวมคลาสที่มีชื่อแตกต่างจากชื่อไฟล์


170

ฉันมีไฟล์Test.javaและรหัสต่อไปนี้อยู่ข้างใน

public class Abcd
{
        //some code here

}

ตอนนี้คลาสไม่ได้คอมไพล์ แต่เมื่อฉันลบโมดิpublicฟายเออร์มันก็คอมไพล์แล้ว

อะไรคือเหตุผลที่อยู่เบื้องหลัง Java ทำให้เราสามารถรวบรวมชื่อคลาสที่แตกต่างจากชื่อไฟล์เมื่อไม่เป็นสาธารณะ

ฉันรู้ว่ามันเป็นคำถามสำหรับมือใหม่ แต่ฉันไม่สามารถหาคำอธิบายที่ดีได้


28
เพราะจาวา (เพราะมันไม่ใช่แบบสาธารณะและไม่ต้องทำตามแบบแผนการตั้งชื่อเดียวกันนอกจากนั้นคุณต้องถามคนที่ประดิษฐ์มันขึ้นมา)
Dave Newton

2
ฉันสงสัยว่ามีคำอธิบายที่ดี มันเป็นข้อกำหนดสำหรับชั้นเรียนสาธารณะ แต่ก็ถือว่าไม่จำเป็นสำหรับชั้นเรียนที่ไม่ใช่แบบสาธารณะ
Kayaman

2
ดูเหมือนคำถามที่คล้ายกัน: stackoverflow.com/questions/7633631/ …
sanket

4
ทำไมมีผู้อัปโหลดจำนวนมากสำหรับคำถามนี้ครั้งแรกของคำถามที่ซ้ำกันทั้งหมด: stackoverflow.com/questions/7633631/ …
GM Ramesh

2
@ Ramesh: ชื่อและเนื้อหาของคำถามนี้จะดีกว่า .. (กว่าคนอื่น ๆ ที่คล้ายกัน)
จายาน

คำตอบ:


325

เหตุผลคืออนุญาตให้มีคลาสระดับบนสุดมากกว่าหนึ่ง.javaไฟล์ต่อไฟล์

มีหลายคลาส - เช่นตัวรับเหตุการณ์ - ใช้เฉพาะที่เท่านั้นและ Java เวอร์ชันแรกสุดไม่สนับสนุนคลาสที่ซ้อน หากไม่มีการผ่อนคลายของกฎ "ชื่อไฟล์ = ชื่อคลาส" แต่ละคลาสดังกล่าวจะต้องใช้ไฟล์ของตัวเองด้วยผลลัพธ์ที่หลีกเลี่ยงไม่ได้ของการเพิ่มจำนวน.javaไฟล์ขนาดเล็กและการกระจัดกระจายของรหัสคู่ที่แน่นหนา

ทันทีที่ Java แนะนำคลาสที่ซ้อนกันความสำคัญของกฎนี้ก็ลดลงอย่างเห็นได้ชัด วันนี้คุณสามารถใช้งานไฟล์ Java ได้หลายร้อยไฟล์โดยไม่ต้องเสี่ยงกับมัน


60
+1 สิ่งนี้ให้เหตุผลซึ่งเป็นคำถาม
เดฟนิวตัน

4
+1 สำหรับข้อมูลประวัติโดยเฉพาะ - ฉันสงสัยว่าด้วยการถือกำเนิดของคลาสที่ซ้อนกัน / ไม่ระบุชื่อหากการตัดสินใจเดียวกันนั้นต้องทำตอนนี้ (ไม่สนใจความเข้ากันได้ย้อนหลัง) มันจะสมเหตุสมผลมากกว่าที่จะยอมให้ระดับบนสุดหนึ่ง ไฟล์.
Michael Berry

1
@ berry120 ค่อนข้างคงที่เพราะค่าเผื่อนี้ทำให้การค้นหาไฟล์ยุ่งยากเมื่อคอมไพล์
Marko Topolnik

3
@Val ปฏิเสธว่าคนอื่นจะใช้โปรแกรมแก้ไขข้อความและเครื่องมือ CLI ในการพัฒนาเพราะคุณมี IDE ที่คุณต้องการอยู่แล้วมันก็งี่เง่าเหมือนการพูดว่าไม่มีประโยชน์ในการสร้าง IDE เพราะคุณสามารถพัฒนาได้โดยไม่ต้องใช้มัน นักพัฒนาที่ดีใช้ทั้งสองวิธีในการสร้างรหัสคุณภาพ และสิ่งเดียวที่เล็กกว่าอัตราต่อรองของนักพัฒนาทั้งหมดที่ได้ตั้งหนึ่งในนั้นและการร้องเพลง kumbaya คืออัตราต่อรองที่เราทุกคนจะเห็นด้วยกับภาษาโปรแกรมที่ดีที่สุดเพียงอย่างเดียว
Dan Is Fiddling โดย Firelight

5
การรวมกันของ Emacs (หรือเป็นกลุ่มรับพิษของคุณ) และสาธารณูปโภคเชลล์ยูนิกซ์ที่อาจจะไม่ได้เป็นทุกอย่างที่-ปลายนิ้วของคุณเป็น IDE ทันสมัยและพวกเขากำลังแน่นอนยากที่จะเรียนรู้ แต่พวกเขามีสองอย่างท่วมท้นข้อได้เปรียบเมื่อเทียบกับ IDE ทุกตัวที่ฉันเคยลอง: พวกมันไม่เคยผิดพลาดไม่ว่า codebase จะใหญ่ขนาดไหนและพวกเขาสามารถพิมพ์ได้ทัน
zwol

80

เหตุผลเป็นเช่นเดียวกับแผ่นประตู หากบุคคลบางคนอยู่ในสำนักงานอย่างเป็นทางการ (ประกาศต่อสาธารณะ) ชื่อของเขา / เธอจะต้องอยู่ที่ป้ายประตู เช่น "Alex Jones" หรือ "Detective Colombo" หากใครบางคนเพียงเข้ามาในห้องคุยกับเจ้าหน้าที่หรือทำความสะอาดพื้นชื่อของพวกเขาไม่จำเป็นต้องใส่อย่างเป็นทางการที่ประตู ประตูสามารถอ่านได้ "ยูทิลิตี้" หรือ "ห้องประชุม" แทน

ชื่ออย่างเป็นทางการหรือ MyClass.java ห้องประชุมหรือ Test.java


4
การเปรียบเทียบที่น่าสนใจอย่างแน่นอน มันอาจจะดีกว่าถ้ามีคำอธิบายเล็กน้อยเกี่ยวกับความเกี่ยวข้องโดยตรง สหกรณ์อาจมีปัญหาบางอย่างที่ทำให้การเชื่อมต่อ (แม้ว่าฉันเข้าใจมันอย่างสมบูรณ์แบบ)
แอนดรูตัดผม

4
@AndrewBarber ฉันไม่คิดว่าการเปรียบเทียบนั้นเหมาะกับมันมากนักเพราะมันไม่ได้เป็นแบบจำลองของคลาสพับลิกชั้นเดียวแชร์ไฟล์กับคลาสแพ็คเกจส่วนตัว มันเหมือนกับการอ่านแผ่นประตู "เฮเทอร์ซานตีผู้จัดการ" แต่ในห้องนั้นมีเฮเธอร์และเลขาทั้งสองของเธอ
Marko Topolnik

@ MarkoTopolnik ฉันไม่ควรมีส่วนร่วมในเรื่องนี้ ฉันอยู่ในคลาส A ที่น่ากลัวในการเปรียบเทียบ! ;)
Andrew Barber

@AndrewBarber ฉันต้องการจะเขียนมันต่อไป; คุณเพิ่งกด :) การเปรียบเทียบก็ล้มเหลวในการแสดงความเป็นห่วงที่สุด: เนื่องจากคุณสมบัตินี้คอมไพเลอร์ต้องแยกวิเคราะห์ไฟล์ทั้งหมดเพื่อค้นหาคลาสทั้งหมดที่ไม่เช่นนั้นก็สามารถอ่านรายชื่อไดเรกทอรีและรู้ชื่อของทั้งหมด ชั้นเรียนระดับบนสุด
Marko Topolnik

@AndrewBarber การเปรียบเทียบที่เหมาะกับความคิดของไดเรกทอรีในทางเดินยาวคุณสามารถค้นหาบุคคลได้อย่างรวดเร็วโดยเพียงแค่เหลือบมองไปที่แผ่นประตูคุณไม่จำเป็นต้องเข้าไปในแต่ละห้องและถาม
exebook

29

ข้อมูลจำเพาะ Java ระบุว่าคุณสามารถมีคลาสพับลิกได้สูงสุดหนึ่งคลาสต่อไฟล์เท่านั้น ในกรณีนี้ชื่อคลาสควรตรงกับชื่อไฟล์ คลาสที่ไม่ใช่แบบสาธารณะทั้งหมดได้รับอนุญาตให้มีชื่อใด ๆ โดยไม่คำนึงถึงชื่อไฟล์


20
แต่ "อะไรคือเหตุผลเบื้องหลังของ Java ที่ยอมให้" สิ่งนี้กับเรา?
Marko Topolnik

@MarkoTopolnik เพราะมันไม่ได้ป้องกันเรา: D
Maroun

8
@MarounMaroun แต่อะไรคือเหตุผลที่อยู่เบื้องหลังไม่ได้ป้องกันเรา?
Marko Topolnik

@Marko Java อนุญาตให้มีหลายคลาสที่กำหนดไว้ในไฟล์เดียวกัน (ตราบเท่าที่มีเพียงหนึ่งคลาสเท่านั้นที่เป็นแบบสาธารณะ) เนื่องจากคลาสทั้งหมดภายในแพ็กเกจเดียวกันต้องมีชื่อแตกต่างกันจึงไม่มีตัวเลือกอื่นนอกเหนือจากการอนุญาตให้คลาสที่ไม่ใช่แบบสาธารณะมีชื่ออื่นนอกเหนือจากชื่อไฟล์
isnot2bad

2
2 เซนต์ของฉัน: บางทีมันอาจได้รับการออกแบบด้วยวิธีนี้เพื่อการแปลที่รวดเร็วขึ้นของคลาสภายใน classpath ด้วยระเบียบนี้การตรวจสอบชื่อไฟล์ / พา ธ นั้นเพียงพอสำหรับการค้นพบคลาส หากไม่มีข้อตกลงนี้คลาสตัวโหลดคลาสพา ธ อาจต้องเปิดและแยกวิเคราะห์ไฟล์เพื่อหาคลาส
Andrei Nicusan

13

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

มีคำอธิบายที่ดีเกี่ยวกับคลาสที่ซ้อนอยู่ทั้งหมดในการสอน Nested Classes Java บนเว็บไซต์ของ Oracle ซึ่งมีตัวอย่างของแต่ละคลาส นอกจากนี้ยังมีเหตุผลที่มีประโยชน์ซึ่งฉันจะพูดถึง:

เหตุใดจึงใช้คลาสที่ซ้อนกัน

เหตุผลที่น่าสนใจสำหรับการใช้คลาสที่ซ้อนกันมีดังนี้:

  • มันเป็นวิธีของการจัดกลุ่มคลาสแบบโลจิคัลที่ใช้ในที่เดียวเท่านั้น : ถ้าคลาสมีประโยชน์กับคลาสอื่นเพียงคลาสเดียวมันก็มีเหตุผลที่จะฝังไว้ในคลาสนั้นและเก็บทั้งสองไว้ด้วยกัน การซ้อน "คลาสผู้ช่วยเหลือ" ดังกล่าวทำให้แพ็คเกจของพวกเขาคล่องตัวขึ้น

  • มันเพิ่มการห่อหุ้ม : พิจารณาคลาสระดับบนสุดสองคลาสคือ A และ B โดยที่ B ต้องการเข้าถึงสมาชิกของ A ที่จะถูกประกาศเป็นส่วนตัว โดยการซ่อนคลาส B ภายในคลาส A สมาชิกของ A สามารถถูกประกาศเป็นส่วนตัวและ B สามารถเข้าถึงพวกเขาได้ นอกจากนี้ B สามารถซ่อนตัวจากโลกภายนอกได้

  • มันสามารถนำไปสู่รหัสที่อ่านได้และบำรุงรักษาได้มากกว่า : การซ้อนคลาสย่อยภายในคลาสระดับบนสุดจะวางโค้ดให้ใกล้กับตำแหน่งที่ใช้มากขึ้น

(เน้นที่เหมือง)

ฉันไม่คุ้นเคยกับ Java spec ในช่วงแรก แต่การค้นหาอย่างรวดเร็วแสดงให้เห็นว่ามีการเพิ่มคลาสภายในใน Java 1.1


สิ่งที่ควรทำในกรณีที่ประเภทมีประโยชน์เฉพาะในประเภทอื่น แต่อินสแตนซ์ของประเภทก่อนหน้าไม่เกี่ยวข้องกับอินสแตนซ์ของหลัง?
supercat

คลาสที่ซ้อนกันคือ Java 1.2 ของการทำ lambdas หรือ 'ฟังก์ชั่น First Class เมื่อทุกอย่างเป็นวัตถุ' นี่คือการเปลี่ยนแปลงใน 1.8 ไวยากรณ์ พวกมันยังถูกใช้เมื่อเราต้องการสร้างแบบจำลองพีชคณิตชนิดข้อมูลในระบบชนิดของ Java
hawkeye

12

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


4

โปรดทราบว่า Java เป็นกรณี ๆ ไป แต่ระบบไฟล์ไม่จำเป็นต้องเป็น หากชื่อฐานของไฟล์คือ "abcd" แต่คลาสเป็น "Abcd" นั่นจะสอดคล้องกับกฎของระบบไฟล์แบบตัวพิมพ์เล็กหรือไม่ ไม่แน่นอนเมื่อถูกพอร์ตไปยังตัวพิมพ์เล็กและตัวพิมพ์ใหญ่

หรือสมมติว่าคุณมีคลาสที่เรียกว่า ABCD และคลาส Abcd (อย่าเข้าใจว่ามันเป็นความคิดที่ไม่ดี: มันอาจเกิดขึ้นได้) และโปรแกรมจะถูกส่งไปยังระบบไฟล์ที่ไม่สนใจขนาดตัวพิมพ์ ตอนนี้คุณไม่เพียง แต่ต้องเปลี่ยนชื่อไฟล์ แต่ยังคลาสโอ๊ะโอ!

หรือถ้าไม่มีไฟล์ล่ะ สมมติว่าคุณมีคอมไพเลอร์ Java ที่สามารถรับอินพุตจากอินพุตมาตรฐาน ดังนั้นคลาสจะต้องมีชื่อว่า "StandardInput"

หากคุณสำรวจความหมายอย่างมีเหตุผลของการกำหนดชื่อไฟล์ให้เป็นไปตามชื่อคลาสคุณจะพบว่ามันเป็นความคิดที่ไม่ดีในหลาย ๆ ทาง


ฉันเห็นด้วยกับสิ่งที่คุณพูด แต่ฉันไม่รู้ว่ามันตอบคำถามโดยเฉพาะอย่างยิ่งยกเว้นบางทีปัญหาบางอย่างที่เกิดจากสถาปัตยกรรมการตั้งชื่ออาจจะปลดเปลื้องได้โดยการอนุญาตให้ชื่อที่ไม่ใช่สาธารณะแตกต่างจาก ชื่อไฟล์ BTW เกี่ยวกับกรณีความไวกับถ้าผมสืบมาภาษาอยู่ในขอบเขตใด ๆFooมีการประกาศตัวระบุFOO, foo, fOoฯลฯ ทุกคนจะได้ "ไม่ได้กำหนด" แม้ว่าพวกเขาจะมีชีวิตอยู่ภายในขอบเขตด้านนอก การออกแบบดังกล่าวจะช่วยลดปัญหาเรื่องตัวพิมพ์เล็กและตัวพิมพ์ใหญ่สำหรับชื่อไฟล์
supercat

3

อีกประเด็นหนึ่งที่หลายคำตอบที่พลาดไม่ได้คือไม่มีการpublicประกาศ JVM จะไม่มีทางรู้ว่าต้องใช้วิธีการหลักของคลาสใด คลาสทั้งหมดที่ประกาศในไฟล์. java เดียวสามารถมีเมธอดหลักได้ แต่เมธอดหลักจะรันเฉพาะคลาสที่ทำเครื่องหมายเป็นพับลิก HTH


0

เนื่องจากไฟล์ java สามารถมีมากกว่าหนึ่งคลาสจึงอาจมีสองคลาสในไฟล์ java หนึ่งไฟล์ แต่ไฟล์ java ต้องมีคลาสที่มีชื่อเหมือนกับชื่อไฟล์หากมีคลาสสาธารณะ


ไม่กฎนั้นใช้ได้กับคลาสสาธารณะเท่านั้น
deadboy
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.