2017-05-17 29 views
9

मैं जावा 9 विनिर्देश की मसौदा पढ़ रहा हूँ में निर्देश खोलता है, लेकिन यह वाक्यांश मेरे लिए स्पष्ट नहीं है:जावा 9

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

यदि खुलने से केवल रनटाइम पर सार्वजनिक और सुरक्षित पहुंच योग्य हो जाता है, तो इसका अर्थ यह है कि संकुल क्षेत्र में सभी प्रकार प्रतिबिंब के माध्यम से सुलभ हैं?

मुझे रनटाइम और प्रतिबिंब के बीच का अंतर समझ में नहीं आता है।

ऐसा लगता है कि खोला गया पैकेज केवल सार्वजनिक और रनटाइम पर सुरक्षित है (प्रतिबिंब के माध्यम से) और अन्य पैकेज जो प्रकार और सदस्यों के साथ सुलभ vie प्रतिबिंब (निजी भी ...) के साथ निर्दिष्ट नहीं हैं।

+1

मुझे नहीं पता कि मैं आपके प्रश्न को सही तरीके से समझता हूं, लेकिन इस बात पर विचार करें कि किसी के पास कोड हो सकता है जो पैकेज में सार्वजनिक एपीआई पर निर्भर करता है। फिर जावा 9 बाहर आता है और पैकेज मॉड्यूल के अंदर encapsulated है। उस विरासत कोड का उपयोग जारी रखने के लिए आपको मॉड्यूल खोलना होगा। –

+0

मैं फिर से व्याख्या करने की कोशिश करता हूं: यदि खुला सभी प्रकार और पैकेज के सभी सदस्यों को प्रतिबिंबित करने की अनुमति देता है तो सार्वजनिक और संरक्षित केस क्यों समझाया जाता है? – xdevel2000

+1

ठीक है धन्यवाद। ठीक है जैसे मैंने कहा, यह हो सकता है कि पैकेज एन्सेप्लेटेड होने से पहले कोई एपीआई (सामान्य तरीका, प्रतिबिंब के माध्यम से नहीं) का उपयोग कर रहा था। यह एक पिछली संगतता सुविधा प्रतीत होता है। –

उत्तर

6

मान लीजिए कि आप कुछ कोड एक पुस्तकालय से एक सार्वजनिक वर्ग का उपयोग करता है लिखते हैं।

import somelibrary.somepackage.SomeClass; // <-- public class from a library. 

public class Main { 

    public static void main(String[] args) { 
     SomeClass.doSomething(); 
    } 

} 

इसके बाद आप इस कोड संकलन है, और यह ठीक संकलित, के बाद से वर्ग का उपयोग कर रहे public है।

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

अपना कोड फिर से काम करने के लिए, आप इस मॉड्यूल को अपने कोड में खोलने के लिए कमांड लाइन विकल्प का उपयोग कर सकते हैं, ताकि यह encapsulated पैकेज का उपयोग जारी रख सके।

वैकल्पिक रूप से, लाइब्रेरी के निर्माता पुस्तकालय की मॉड्यूल परिभाषा में opens somepackage; जोड़ सकते हैं। इससे आपको इस नए संस्करण का उपयोग करके अपने कोड को अनुमति देगा, लेकिन इसके साथ संकलित नहीं करेगा। अर्थात। public और protected सदस्य केवल रनटाइम पर पहुंच योग्य हैं, लेकिन इसमें कोई प्रतिबिंब शामिल नहीं है।


एक ही है जब आप एक वर्ग का विस्तार, और समझाया पैकेज में है कि एक सुपर वर्ग के एक protected सदस्य तक पहुँचने के लिए चाहते हैं के लिए चला जाता है।

लेकिन निर्देश खोलता है तथ्य यह है कि अगर एक पुस्तकालय के अगले संस्करण में, एक विधि या क्षेत्र private किया जाता है नहीं बदलता है, कि आप एक IllegalAccessError मिल अगर आप इसे इस्तेमाल करने की कोशिश:

class SomeClass { // <-- the class in the library 
    public static void doSomething() { 
     System.out.println("doSomething"); // contrived example code 
    } 
} 

...

public class Main {  
    public static void main(String... args) throws Exception {  
     SomeClass.doSomething(); // this call compiles fine, 
    }  
} 

फिर, पुस्तकालय doSomething के अगले संस्करण में private बना है:

private static void doSomething() {...} 

और पुनः संकलित। लेकिन अगर आप Main के पुराने संस्करण को SomeClass के नए संस्करण के साथ चलाने का प्रयास करते हैं तो आपको IllegalAccessError मिलता है।

संक्षेप में, केवल उन सदस्यों के लिए काम करता है जो लाइब्रेरी के नए संस्करण में public या protected हैं। तो प्रतिबिंब के मामले में

public static void main(String... args) throws Exception {  
    Method m = SomeClass.class.getDeclaredMethod("doSomething"); 
    m.setAccessible(true); 
    m.invoke(null); // works Fine 
} 

, खुलता भी फिर से समझाया होगा निजी सदस्यों सुलभ:


हालांकि, प्रतिबिंब के मामले में, आप हमेशा एक private सदस्य पहुँच सकते हैं, setAccessible(true) का उपयोग करके ।

+0

हां, यह एक अच्छा जवाब है इसलिए मैंने मतदान किया लेकिन इस मामले में मैं निजी सदस्यों तक भी पहुंच सकता हूं ... इसलिए फिर मैं विनिर्देश में व्यक्त मतभेदों को समझ नहीं पा रहा हूं। ईमानदारी से @xenteros द्वारा पोस्ट किए गए दस्तावेज़ों में जो कहा गया है उसे मंजूरी दे दी गई है, लेकिन साथ ही मुझे नहीं लगता कि विनिर्देश त्रुटि में है .... अगर यह ड्राफ्ट में भी है! – xdevel2000

+1

@ xdevel2000 नहीं, आप इस मामले में 'निजी' सदस्यों तक नहीं पहुंच सकते हैं (जहां आप 'सार्वजनिक' एपीआई के खिलाफ संकलित करते हैं, जिसे बाद के संस्करण में 'निजी' बनाया जाता है)। आपको 'IllegalAccessError' मिलेगा, और खोलने से इसका उपयोग नहीं बदलेगा। –

+0

कृपया, क्या आप मुझे IllegalAccessError का पूरा उदाहरण प्रदान कर सकते हैं? अब मैं इसे अपने आप से नहीं कर सकता ... यदि आप कर सकते हैं, तो निश्चित रूप से :) – xdevel2000

3

मॉड्यूल द्वारा खोला गया पैकेज योग्य या अयोग्य हो सकता है।

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

--Documentation

+0

अच्छा ... तो यह विनिर्देश के साथ विरोधाभास में लगता है ... शायद क्योंकि यह मसौदे में है? – xdevel2000

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