java - प्रत्येक सार्वजनिक वर्ग एक अलग फ़ाइल में क्यों है?




code-organization (8)

मैंने हाल ही में जावा सीखना शुरू कर दिया और यह बहुत अजीब पाया कि प्रत्येक जावा क्लास को एक अलग फ़ाइल में घोषित किया जाना चाहिए। मैं एक सी # प्रोग्रामर हूं और सी # इस तरह के प्रतिबंध को लागू नहीं करता है।

जावा ऐसा क्यों करता है? क्या कोई डिजाइन विचार था?

संपादित करें (कुछ उत्तरों के आधार पर):

जावा अब आईडीई की उम्र में इस प्रतिबंध को क्यों नहीं हटा रहा है? यह किसी भी मौजूदा कोड को तोड़ नहीं देगा (या यह होगा?)।


आईडीई की उम्र में जावा अब इस प्रतिबंध को क्यों नहीं हटा रहा है? यह किसी भी मौजूदा कोड को तोड़ नहीं देगा (या यह होगा?)।

अब सभी कोड एक समान है। जब आप एक स्रोत फ़ाइल देखते हैं तो आप जानते हैं कि क्या उम्मीद करनी है। यह हर परियोजना के लिए समान है। यदि जावा इस सम्मेलन को हटाना था तो आपको जिस परियोजना पर काम करना है, उसके लिए आपको कोड संरचना जारी करनी होगी, जहां अब आप इसे एक बार सीखते हैं और इसे हर जगह लागू करते हैं। हमें सब कुछ के लिए आईडीई पर भरोसा नहीं करना चाहिए।


इस तरह भाषा डिजाइनरों ने ऐसा करने का फैसला किया। मुझे लगता है कि मुख्य कारण संकलक पास-थ्रू को अनुकूलित करना था - संकलक को सार्वजनिक कक्षाओं का पता लगाने के लिए फ़ाइलों के माध्यम से अनुमान लगाने या विश्लेषण करने की आवश्यकता नहीं है। मुझे लगता है कि यह वास्तव में एक अच्छी बात है, यह कोड फ़ाइलों को खोजने में बहुत आसान बनाता है, और आपको एक फ़ाइल में बहुत अधिक डालने से दूर रहने के लिए मजबूर करता है। मुझे यह भी पसंद है कि जावा आपको अपनी कोड फ़ाइलों को उसी निर्देशिका संरचना में पैकेज के रूप में रखने के लिए कैसे मजबूर करता है - जो किसी भी कोड फ़ाइल को ढूंढना आसान बनाता है।


खैर, वास्तव में यह जावा भाषा विशिष्टता (धारा 7.6, पृष्ठ संख्या 20 9) के अनुसार एक वैकल्पिक प्रतिबंध है, लेकिन इसके बाद ओरेकल जावा कंपाइलर अनिवार्य प्रतिबंध के रूप में है। जावा भाषा विशिष्टता के अनुसार,

जब किसी फ़ाइल सिस्टम (§7.2.1) में संकुल संग्रहीत किए जाते हैं, तो मेजबान सिस्टम प्रतिबंध लागू करने का विकल्प चुन सकता है कि यह एक संकलित-समय त्रुटि है यदि किसी प्रकार के नाम के नाम से फ़ाइल में कोई प्रकार नहीं मिलता है एक विस्तार (जैसे .java या .jav) यदि निम्न में से कोई भी सत्य है:

  • इस प्रकार को पैकेज द्वारा अन्य संकलन इकाइयों में कोड द्वारा संदर्भित किया जाता है जिसमें प्रकार घोषित किया जाता है।
  • इस प्रकार को सार्वजनिक घोषित किया जाता है (और इसलिए अन्य पैकेजों में कोड से संभावित रूप से सुलभ है)।

इस प्रतिबंध का तात्पर्य है कि प्रति संकलन इकाई में ऐसे एक प्रकार का होना चाहिए। यह प्रतिबंध एक जावा कंपाइलर के लिए एक पैकेज के भीतर एक नामित कक्षा खोजने के लिए आसान बनाता है।

व्यावहारिक रूप से, कई प्रोग्रामर प्रत्येक कक्षा या इंटरफ़ेस प्रकार को अपनी संकलन इकाई में रखना चुनते हैं, चाहे वह सार्वजनिक हो या अन्य संकलन इकाइयों में कोड द्वारा संदर्भित किया गया हो।

उदाहरण के लिए, सार्वजनिक प्रकार wet.sprocket.Toad के लिए स्रोत कोड निर्देशिका गीले / स्पॉकेट में फ़ाइल Toad.java में मिलेगा, और इसी ऑब्जेक्ट कोड को उसी निर्देशिका में फ़ाइल Toad.class में मिलेगा।

अधिक स्पष्ट तस्वीर प्राप्त करने के लिए कल्पना करें कि दो सार्वजनिक कक्षाएं सार्वजनिक कक्षा ए और पब्लिक क्लास बी एक ही स्रोत फ़ाइल में हैं और ए क्लास में अभी तक संकलित कक्षा बी का संदर्भ नहीं है और हम संकलन (संकलन-लिंकिंग-लोडिंग) कक्षा ए को संकलित कर रहे हैं अब कक्षा बी कंपाइलर को जोड़ने के दौरान वर्तमान पैकेज के भीतर प्रत्येक * .java फ़ाइलों की जांच करने के लिए मजबूर होना होगा क्योंकि कक्षा बी में इसकी विशिष्ट बीजेवी फ़ाइल नहीं है। तो उपर्युक्त मामले में, यह संकलक के लिए थोड़ा सा समय लगता है कि कौन सी कक्षा स्रोत स्रोत के अंतर्गत है और किस वर्ग में मुख्य विधि है। तो एक स्रोत वर्ग प्रति स्रोत फ़ाइल को रखने के पीछे कारण वास्तव में संकलन प्रक्रिया को तेजी से बनाना है क्योंकि यह स्रोत (आयात विवरण) लिंक के दौरान स्रोत और संकलित फ़ाइलों के अधिक कुशल लुकअप को सक्षम बनाता है। विचार यह है कि यदि आप कक्षा के नाम को जानते हैं, तो आप जानते हैं कि प्रत्येक क्लासपाथ एंट्री के लिए यह कहां पाया जाना चाहिए और कोई अनुक्रमण की आवश्यकता नहीं होगी।

और जैसे ही हम अपने आवेदन को निष्पादित करते हैं, जेवीएम डिफ़ॉल्ट रूप से सार्वजनिक वर्ग के लिए दिखता है (क्योंकि कोई प्रतिबंध नहीं है और कहीं से भी पहुंचा जा सकता है) और सार्वजनिक कक्षा में public static void main(String args[]) भी दिखता है। पब्लिक क्लास प्रारंभिक कक्षा के रूप में कार्य करता है जहां जावा एप्लिकेशन (प्रोग्राम) के लिए जेवीएम इंस्टेंस शुरू हो गया है। इसलिए जब हम एक कार्यक्रम में एक से अधिक सार्वजनिक वर्ग प्रदान करते हैं तो संकलक स्वयं आपको एक त्रुटि फेंक कर रोक देता है। ऐसा इसलिए है क्योंकि बाद में हम जेवीएम को भ्रमित नहीं कर सकते हैं कि किस कक्षा में इसकी प्रारंभिक कक्षा है क्योंकि public static void main(String args[]) साथ केवल एक सार्वजनिक वर्ग JVM के लिए प्रारंभिक कक्षा है।

आप एक और अधिक पढ़ सकते हैं कि एकल जावा स्रोत फ़ाइल में एक सार्वजनिक वर्ग से अधिक क्यों नहीं हो सकता है


मैंने अभी सी # समाधान लिया है और केवल यह किया है (किसी भी फाइल को हटाएं जिसमें उनमें कई सार्वजनिक वर्ग थे) और उन्हें अलग-अलग फाइलों में तोड़ दिया और इससे जीवन को और आसान बना दिया गया।

यदि आपके पास फ़ाइल में कई सार्वजनिक कक्षाएं हैं तो आपके पास कुछ समस्याएं हैं:

  1. आप फ़ाइल का नाम क्या रखते हैं? सार्वजनिक कक्षाओं में से एक? दूसरा नाम? लोगों के पास एक अतिरिक्त मुद्दा रखने के लिए खराब समाधान कोड संगठन और फ़ाइल नामकरण सम्मेलनों के आसपास पर्याप्त समस्याएं हैं।

  2. साथ ही, जब आप फ़ाइल / प्रोजेक्ट एक्सप्लोरर को ब्राउज़ कर रहे हैं तो यह अच्छा है कि चीजें छिपी नहीं हैं। उदाहरण के लिए आप एक फ़ाइल देखते हैं और ड्रिल करते हैं और 200 कक्षाएं एक साथ मिलती हैं। यदि आपके पास एक फ़ाइल एक वर्ग है, तो आप अपने परीक्षणों को बेहतर तरीके से व्यवस्थित कर सकते हैं और समाधान की संरचना और जटिलता के लिए एक महसूस कर सकते हैं।

मुझे लगता है कि जावा को यह अधिकार मिला।


यह Foobar.class से Foobar.java तक जाने के लिए सरल हेरिस्टिक के लिए अनुमति देता है।

यदि फूबर किसी भी जावा फ़ाइल में हो सकता है तो आपके पास मैपिंग समस्या हो सकती है, जिसका अंततः मतलब हो सकता है कि आपको कक्षा की परिभाषा का पता लगाने के लिए सभी जावा फाइलों का पूरा स्कैन करना होगा।

व्यक्तिगत रूप से मैंने यह अजीब नियमों में से एक पाया है जो संयुक्त अनुप्रयोगों में परिणामस्वरूप बहुत बड़ा हो सकता है और अभी भी मजबूत हो सकता है।


यह एक फ़ाइल में एकाधिक जावा शीर्ष स्तर के वर्गों के लिए तकनीकी रूप से कानूनी है। हालांकि इसे खराब अभ्यास माना जाता है, और यदि आप ऐसा करते हैं तो कई जावा टूल्स (आईडीई समेत) काम नहीं करते हैं।

जेएलएस यह कहता है:

जब किसी फ़ाइल सिस्टम (§7.2.1) में संकुल संग्रहीत किए जाते हैं, तो मेजबान सिस्टम प्रतिबंध लागू करने का विकल्प चुन सकता है कि यह एक संकलित-समय त्रुटि है यदि किसी प्रकार के नाम के नाम से फ़ाइल में कोई प्रकार नहीं मिलता है एक विस्तार (जैसे .java या .jav) यदि निम्न में से कोई भी सत्य है:

  • इस प्रकार को पैकेज द्वारा अन्य संकलन इकाइयों में कोड द्वारा संदर्भित किया जाता है जिसमें प्रकार घोषित किया जाता है।
  • इस प्रकार को सार्वजनिक घोषित किया जाता है (और इसलिए अन्य पैकेजों में कोड से संभावित रूप से सुलभ है)।

जेएलएस पाठ में मई के उपयोग पर ध्यान दें। यह कहता है कि एक कंपाइलर इसे अमान्य के रूप में अस्वीकार कर सकता है, या ऐसा नहीं हो सकता है। यदि आप स्रोत कोड स्तर पर पोर्टेबल होने के लिए अपना जावा कोड बनाने की कोशिश कर रहे हैं तो यह एक अच्छी स्थिति नहीं है । इस प्रकार, भले ही एक स्रोत फ़ाइल में कई वर्ग आपके विकास प्लेटफॉर्म पर काम करते हैं, यह करने के लिए यह बुरा अभ्यास है।

मेरी समझ यह है कि यह "अस्वीकार करने की अनुमति" एक डिज़ाइन निर्णय है जिसका उद्देश्य प्लेटों की विस्तृत श्रृंखला पर जावा को कार्यान्वित करना आसान बनाना है। यदि (विपरीत रूप से) जेएलएस को सभी कंप्यूटर्स को कई कक्षाओं वाली स्रोत फ़ाइलों का समर्थन करने की आवश्यकता होती है, तो ऐसे प्लेटफॉर्म पर जावा को लागू करने वाले वैचारिक मुद्दे होंगे जो फ़ाइल-सिस्टम आधारित नहीं थे।

अभ्यास में, अनुभवी जावा डेवलपर्स को ऐसा करने में सक्षम होने से चूकना नहीं है। मॉड्यूलरलाइजेशन और सूचना छिपाने के लिए पैकेज, क्लास एक्सेस संशोधक और आंतरिक या घोंसले वाले वर्गों के उचित संयोजन का उपयोग करके बेहतर किया जाता है।


वास्तव में सवाल का जवाब नहीं है लेकिन डेटा बिंदु कम नहीं है।

मैंने अपनी व्यक्तिगत सी ++ उपयोगिता लाइब्रेरी के शीर्षलेखों को पकड़ लिया (आप इसे here से प्राप्त कर सकते here ) और लगभग सभी हेडर फाइलें जो वास्तव में कक्षाएं घोषित करती हैं (कुछ केवल मुक्त फ़ंक्शंस घोषित करती हैं) एक से अधिक कक्षा घोषित करती हैं। मैं खुद को एक बहुत अच्छा सी ++ डिजाइनर के रूप में सोचना पसंद करता हूं (हालांकि लाइब्रेरी स्थानों में एक बॉज का थोड़ा सा है - मैं उसका एकमात्र उपयोगकर्ता हूं), इसलिए मेरा सुझाव है कि कम से कम सी ++ के लिए, एक ही फाइल में कई कक्षाएं सामान्य हैं और यहां तक ​​कि अच्छा अभ्यास भी।


जावा में सोच से

:

प्रति संकलन इकाई (फ़ाइल) में केवल एक सार्वजनिक वर्ग हो सकता है।
विचार यह है कि प्रत्येक संकलन इकाई में एक सार्वजनिक सार्वजनिक इंटरफेस होता है जो उस सार्वजनिक वर्ग द्वारा दर्शाया जाता है । जैसा कि आप चाहते हैं उतने सहायक "दोस्ताना" कक्षाएं हो सकती हैं। यदि आपके पास संकलन इकाई के अंदर एक से अधिक सार्वजनिक वर्ग हैं, तो संकलक आपको एक त्रुटि संदेश देगा।

विनिर्देशन से (7.2.6)

जब किसी फ़ाइल सिस्टम (? 7.2.1) में संकुल संग्रहीत किए जाते हैं, तो मेजबान सिस्टम प्रतिबंध लागू करने का विकल्प चुन सकता है कि यह एक संकलित-समय त्रुटि है यदि किसी प्रकार के नाम के नाम से फ़ाइल में कोई प्रकार नहीं मिलता है एक विस्तार (जैसे .java या .jav) यदि निम्न में से कोई भी सत्य है :

  • इस प्रकार को पैकेज द्वारा अन्य संकलन इकाइयों में कोड द्वारा संदर्भित किया जाता है जिसमें प्रकार घोषित किया जाता है।
  • इस प्रकार को सार्वजनिक घोषित किया जाता है (और इसलिए अन्य पैकेजों में कोड से संभावित रूप से सुलभ है)।
  • इस प्रतिबंध का तात्पर्य है कि प्रति संकलन इकाई में ऐसे एक प्रकार का होना चाहिए।
  • यह प्रतिबंध जावा प्रोग्रामिंग भाषा के लिए एक कंपाइलर या जावा वर्चुअल मशीन के कार्यान्वयन के लिए एक पैकेज के भीतर एक नामित वर्ग खोजने के लिए आसान बनाता है ; उदाहरण के लिए, सार्वजनिक प्रकार wet.sprocket.Toad के लिए स्रोत कोड निर्देशिका गीले / स्पॉकेट में फ़ाइल Toad.java में मिलेगा, और संबंधित ऑब्जेक्ट कोड उसी निर्देशिका में फ़ाइल Toad.class में मिलेगा।

संक्षेप में: यह आपके क्लासपाथ पर सबकुछ लोड किए बिना कक्षाएं ढूंढने के बारे में हो सकता है।

संपादित करें: "चुन सकता है" ऐसा लगता है कि यह उस प्रतिबंध का पालन करने की संभावना छोड़ देता है, और "मई" का अर्थ आरएफसी 2119 (यानी "वैकल्पिक") में वर्णित है
अभ्यास में हालांकि, यह इतने सारे प्लेटफ़ॉर्म में लागू किया गया है और इतने सारे टूल और आईडीई द्वारा निर्भर किया गया है कि मुझे उस प्रतिबंध को लागू करने के लिए कोई भी "होस्ट सिस्टम" नहीं दिख रहा है।

" एक बार ओक पर ... " से

यह बहुत स्पष्ट है - जैसे कि ज्यादातर चीजें डिजाइन कारणों को जानती हैं - संकलक को सभी संकलन इकाइयों (.java फाइलों) के माध्यम से अतिरिक्त कक्षाएं बनाना पड़ता है ताकि यह पता चल सके कि कक्षाएं कहां थीं, और इससे संकलन भी धीमा हो जाएगा ।

(ध्यान दें:

ओक संस्करण 0.2 (पोस्टस्क्रिप्ट दस्तावेज़) के लिए ओक भाषा विशिष्टता : ओक मूल रूप से जावा के नाम से जाना जाने वाला मूल नाम था, और यह मैनुअल ओक (यानी जावा) के लिए सबसे पुराना मैनुअल उपलब्ध है।
जावा की उत्पत्ति पर अधिक इतिहास के लिए, कृपया ग्रीन प्रोजेक्ट और जावा (टीएम) प्रौद्योगिकी: एक प्रारंभिक इतिहास देखें
)






code-organization