2017-04-16 8 views
6
public class StaticTest { 

    private static String a; 
    private static String b = "this is " + a; 

    public static void main(String[] args) { 
     a = "test"; 

     System.out.println(b); // prints "this is null" 
    } 

} 

मैं b के मूल्य के बारे में उलझन में हूं। मुझे लगता है कि परिणाम "यह परीक्षण है" होना चाहिए, लेकिन परिणाम "यह शून्य है"। क्यूं कर?यह जावा स्थिर क्षेत्र शून्य क्यों है?

+8

कक्षा लोड के दौरान स्टेटिक फ़ील्ड शुरू किया गया था। इस समय 'ए' 'शून्य 'था। – Oleksandr

उत्तर

4

आप स्ट्रिंग बी को स्ट्रिंग जोड़ते हैं लेकिन स्ट्रिंग को अभी तक परिभाषित नहीं किया गया है। आपको इसे परिभाषित करने के बाद इसे स्ट्रिंग बी में जोड़ना चाहिए।

private static String a = "test"; 
private static String b = "this is a " + a; 
public static void main(String [] args){ 
    System.out.println(b); 
} 
+0

लेकिन परिवर्तनों के दौरान मैं बदलना चाहता हूं। मुझे यह प्रभाव चाहिए। मुझे क्या करना चाहिए? – JianWan

2

आप

private static String a; 
private static String b = "this is " + a; 

किया इस बिंदु पर, anull था। इसलिए, Stringb बन

this is null 

अब, a में कोई परिवर्तन b पर प्रतिबिंबित नहीं होता। इसलिए, यह परिणाम। अपेक्षित परिणाम के लिए,

private String a = "test"; 
private String b = "this is " + a; 
6

अन्य लोगों ने समझाया है कि यह ऐसा क्यों काम करता है।

हालांकि, जब आप इसका संदर्भ देते हैं तो मूल्य गणना करने के तरीके हैं।

private static String a; 
private static Supplier<String> bSupplier =()->"this is " + a; 

public static void main(String[] args){ 
    a = "test"; 
    System.out.println(bSupplier.get()); //Prints "this is a test" 
} 

जब आप bSupplier.get() पर कॉल करते हैं तो मूल्य की गणना की जाती है। यदि आप a का मान बदलते हैं, और इसे फिर से कॉल करते हैं, तो मान नए मान को प्रतिबिंबित करेगा।

ऐसा कुछ नहीं है जो आपको अक्सर करना चाहिए, लेकिन यह जानना उपयोगी है।

1

तो, बाहर शुरू करने के लिए, जब आप अपने कार्यक्रम चलाने के लिए, उन स्थिर क्षेत्रों आपका मुख्य विधि से पहले सेट कर रहे हैं आदेश है कि वे परिभाषित कर रहे हैं में चलाया जाता है, है, तो anull करने के लिए सेट हो जाता है, और b"this is null" करने के लिए सेट हो जाता है, और फिर आपकी मुख्य विधि चलती है, a बनाने का मूल्य "test" है। जब यह

private static String b = "this is" + a; 

Is लेता "this is" देखता है और यह पर मूल्य a की देता

क्या जावा करता है। यदि a का मान बाद में बदलता है, b का मान नहीं होगा, क्योंकि b परिवर्तनीय a पर एक लिंक संग्रहीत नहीं करता है, तो यह केवल उस मान को संग्रहीत करता है जो इसे सौंपा गया था।

3

लेकिन परिवर्तनों के दौरान मैं बदलना चाहता हूं। मुझे यह प्रभाव चाहिए। मुझे क्या करना चाहिए?

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

b के लिए स्थैतिक क्षेत्र का उपयोग करने में आपके मामले में आपकी आवश्यकता का समाधान नहीं है।
b एक स्थिर विधि getB() कि जहां यह शुरू हो जाती है समय वर्तमान a मूल्य के अनुसार एक String उदाहरण देता है बल्कि होना चाहिए:

public class StaticTest { 

    private static String a; 

    public static void main(String[] args) { 
     a = "test";  
     System.out.println(getB()); 
    } 

    private static String getB(){ 
     return "this is " + a;  
    } 
} 

पुनश्च: यह स्टीवन Lowes के जवाब से एक करीबी पर्याप्त तरीका है कि जब classloader JVM में एक वर्ग को लोड करता है जावा 8.

+0

क्या हम एक संदर्भ के साथ, संलग्न नहीं कर सकते हैं? मेरा मतलब है, अब के लिए मैं समझता हूं कि '+' या '.concat', 'स्ट्रिंग' के अंत में' अक्षर 'की प्रतिलिपि बनाता है। क्या होगा यदि हम संभवतः 'स्ट्रिंगबिल्डर' का संदर्भ संलग्न करना चाहते हैं, और फिर इसकी सामग्री को म्यूट करें, और ऑरगनल 'स्ट्रिंग' में परिवर्तन देखें। क्या यह संभव है ? –

+0

अच्छा, मुझे यह पसंद है। धन्यवाद। – JianWan

+0

@Shashwat स्ट्रिंग्स अपरिवर्तनीय हैं। 'स्ट्रिंगबिल्डर' में शामिल किसी भी 'स्ट्रिंग' को अन्य 'स्ट्रिंग' उदाहरणों पर दुष्प्रभाव नहीं हो सकता है। – davidxxx

1

के लिए विशिष्ट है, यह तीन चरणों

1.) लोड

में यह करता है

2.) लिंक (जो आगे तीन चरणों में बांटा गया है (एक अर्थात्।) को सत्यापित, (ख।) तैयार, (सी।) संकल्प)

3.) प्रारंभ

तो दौरान तैयार (लिंक) चरण क्लासलोडर स्थैतिक चर प्रारंभ करता है (उदाहरण नहीं) और उन्हें अपने डिफ़ॉल्ट प्रारंभिक मानों (वास्तविक मान नहीं) पर सेट करता है, और स्ट्रिंग के लिए यह शून्य है।

अब प्रारंभिक चरण के दौरान स्थिर चर को उनके वास्तविक मूल्य को आवंटित किया जाता है और अभी भी anull है। क्योंकि main विधि इस चरण के बाद चल जाएगी।

तो मुख्य a अंदर मूल्य "test" असाइन किया गया है और पहले से ही b, आरंभीकरण के दौरान classloader द्वारा आवंटित किया जाता है जब a बातिल था ताकि कारण स्ट्रिंग b अजीब उत्पादन किया है।

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