2016-12-16 3 views
12

मैं follwing जावा 9 मॉड्यूल है:आंतरिक प्रकारों को लीक करने वाले सार्वजनिक एपीआई का संकलन क्यों विफल नहीं होता है?

module com.example.a { 
    exports com.example.a; 
} 

एक निर्यात प्रकार के साथ:

public class Api { 

    public static void foo(ImplDetail args) {} 
} 

और एक गैर-निर्यात के प्रकार:

package com.example.b.internal; 

public class ImplDetail {} 

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

मेरे आश्चर्य के लिए, यह मॉड्यूल जैवैक द्वारा सफलतापूर्वक संकलित किया गया है। मैं null पास करने का विशेष मामला देख सकता हूं, फिर भी मैं ऐसी एपीआई परिभाषा को विकृत मानता हूं और सोचता हूं कि इसे समर्थित नहीं किया जाना चाहिए, आदर्श रूप से संकलक द्वारा लागू किया गया है।

ऐसे मामले को अस्वीकार करने का तर्क क्या है?

उत्तर

8

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

ध्यान दें कि सार्वजनिक एपीआई में निजी प्रकार का उपयोग करना हमेशा संभव है, जावा 1.0 पर वापस जाकर।

आपने पहले से ही नोट किया है कि मॉड्यूल के बाहर कोड अभी भी Api.foo(null) पर कॉल कर सकता है।

ऐसे अन्य मामले भी हैं जहां एक कॉलर अभी भी इस एपीआई को गैर-शून्य संदर्भ के साथ उपयोग कर सकता है। com.example.a पैकेज में public class Sub extends ImplDetail कक्षा पर विचार करें। यह वर्ग Sub सार्वजनिक है और निर्यात किया जाता है और मॉड्यूल के बाहर कोड के लिए भी उपलब्ध है। इस प्रकार, बाहरी कोड कहीं से प्राप्त Sub के उदाहरणों का उपयोग करके Api.foo(sub) पर कॉल कर सकता है।

लेकिन निश्चित रूप से, जावैक बता सकता है कि किसी भी निर्यात किए गए पैकेज में ImplDetail के कोई उपप्रकार हैं, और यदि कोई नहीं है तो संकलन-समय त्रुटि जारी करें? जरुरी नहीं। अलग संकलन की संभावना के कारण, संकलन चरण के बाद मॉड्यूल में नए वर्गों को पेश किया जा सकता है जिसमें Api शामिल है। या, उस मामले के लिए, मॉड्यूल-info.class फ़ाइल को निर्यात किए गए पैकेजों के सेट को बदलने के लिए पुनः संकलित किया जा सकता है।

इन कारणों से मुझे लगता है कि यह उस समय त्रुटि उत्पन्न करने के लिए अनुचित है जब यह Api कक्षा को संकलित करता है। जावाक के पास -Xlint:exports विकल्प है जो इस तरह के मामलों को चेतावनी के रूप में ध्वजांकित करेगा।

कुछ समय बाद निर्माण प्रक्रिया में, जैसे कि जेएमओडी उपकरण, या कुछ वास्तविक तथ्य मॉड्यूल ऑडिटिंग टूल, निर्यात किए गए एपीआई में इस्तेमाल किए जाने वाले गैर-निर्यात किए गए प्रकार के उपयोग को भी ध्वजांकित कर सकता है। मुझे नहीं लगता कि वर्तमान में कुछ भी ऐसा करता है, हालांकि।

+0

आपके विस्तृत उत्तर के लिए धन्यवाद, स्टुअर्ट! एक गैर-निर्यात किए गए प्रकार से निर्यात किए गए प्रकार को प्राप्त करना मेरे लिए उतना ही असंगत लगता है, इसलिए मैंने कहा होगा कि अकेले को एक संकलन त्रुटि ('उप' के लिए) वारंट करना चाहिए। लेकिन शायद एक ही समस्या होगी जो आप कई संकलन चरणों के साथ वर्णन करते हैं। – Gunnar

+0

@ गुन्नर थोड़ी देर के लिए इस पर विचार करने के बाद, मुझे एहसास हुआ कि यह एक निजी वर्ग का उप-वर्ग है जो सार्वजनिक वर्ग के लिए उचित (यदि असामान्य) है।जेडीके में, उदाहरण के लिए, जावा.लांग में, 'स्ट्रिंगबफर' और 'स्ट्रिंगबिल्डर' एक निजी वर्ग 'सारस्ट्रिंगबिल्डर' के सार्वजनिक उप-वर्ग हैं। पदानुक्रम एसबी <: एएसबी <: एक इंटीरियर निजी वर्ग के साथ वस्तु है, लेकिन यह कार्यान्वयन साझा करने के लिए किया गया है, यह थोड़ा अजीब है। ध्यान दें कि एएसबी को एपीआई में एक प्रकार के रूप में उजागर नहीं किया गया है। –

+0

फॉलो-अप के लिए धन्यवाद। व्यक्तिगत रूप से, मुझे इस तरह के डिजाइन अजीब लगता है। एक प्रकार का उपयोगकर्ता एक प्रकार के आईएमओ के पूर्ण पदानुक्रम को देखने में सक्षम होना चाहिए। यदि यह कार्यान्वयन साझा करने के बारे में है, तो यह प्रतिनिधिमंडल के माध्यम से एक निजी साझा कक्षा में किया जा सकता है। – Gunnar

संबंधित मुद्दे