2009-12-02 18 views
34

मैं इस तरह विरासत कोड का एक बहुत कुछ देखने पर प्रशिक्षु() उपयोग कब करें:)स्ट्रिंग शाब्दिक

class A { 
    public static final String CONSTANT = "value".intern(); 
    ... 
} 

मैं प्रशिक्षु (के लिए किसी भी कारण नहीं दिख रहा है, जावाडोक एक पढ़ सकते हैं के रूप में: "सभी शाब्दिक तार और स्ट्रिंग-मूल्यवान निरंतर अभिव्यक्तियों को प्रशिक्षित किया जाता है।" क्या इसका कोई इरादा है, शायद भाषा के पिछले संशोधन में?

+7

क्या पीजीपी के अलावा कोई भी वास्तव में इसका जवाब देने से पहले इस प्रश्न को पढ़ता था? – Adamski

+0

संभावित डुप्लिकेट [क्या सभी संकलन-समय स्थिरांक रेखांकित हैं?] (Http://stackoverflow.com/questions/377819/are-all-compile-time-constants-inlined) –

उत्तर

65

यह सुनिश्चित करना है कि CONSTANT वास्तव में एक स्थिर नहीं है एक तकनीक है।

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

"निरंतर" स्ट्रिंग पर प्रशिक्षु() कॉल करने से, यह नहीं रह गया है संकलक द्वारा एक स्थिर निरंतर माना जाता है, इसलिए वर्ग का उपयोग कर वास्तव में एक प्रयोग पर परिभाषित करने क्लास 'सदस्य का उपयोग करेंगे।


JLS प्रशंसा पत्र:

+4

अब मैं एक चाल – pjp

+1

कहूंगा, मैंने अभी प्रयोगात्मक रूप से पुष्टि की है, लेकिन क्या कोई जेएलएस उद्धरण है? –

+0

यह http://stackoverflow.com/questions/377819/are-all-compile-time-constants-inlined – pjp

16

शाब्दिक लगातार तार के साथ intern() के उपयोग के रूप The Java® Language Specification की धारा 3.10.5. String Literals द्वारा निर्दिष्ट शाब्दिक रूप में समय की बर्बादी को पहले से ही प्रशिक्षु हो जाएगा।

जावा SE 8 संस्करण से हवाला देते हुए:

इसके अलावा, एक स्ट्रिंग हमेशा शाब्दिक वर्ग स्ट्रिंग का एक ही उदाहरण को दर्शाता है। ऐसा इसलिए है क्योंकि स्ट्रिंग अक्षर - या, आमतौर पर, स्ट्रिंग्स जो निरंतर अभिव्यक्तियों के मूल्य हैं (§15.28) - "interned" हैं ताकि विधि String.intern का उपयोग करके अद्वितीय उदाहरण साझा कर सकें।

मुझे लगता है कि कोडर इस तथ्य की सराहना नहीं करता था।

संपादित करें:

kdgregory के रूप में बताया गया है कि कैसे इस निरंतर inlined किया जा सकता है पर एक प्रभाव है।

1-https://docs.oracle.com/javase/specs/jls/se8/html/jls-3.html#jls-3.10.5

+3

जेएलएस परिणामों के बारे में बात करता है, लेकिन यह स्पष्ट नहीं है चाहे यह फोल्डिंग संकलन-समय पर होती है, या फिर यह है कि रन-टाइम पर संकलन-समय तहखाने और concatenate-and-intern-intern के बीच कोई अवलोकन अंतर नहीं होना चाहिए। बाइट कोड निरीक्षण का जवाब होगा कि दो स्ट्रिंग समेकित अक्षर कक्षा फ़ाइल में से एक बन गए हैं या नहीं। – seh

5

कुछ समय पहले मैं प्रशिक्षु() एड सब ओ एफ स्ट्रिंग्स क्लास फाइलों से आ रही हैं (क्लासफाइल पार्सर के लिए)। प्रशिक्षु() आईएनजी प्रोग्राम का उपयोग कम स्मृति (इस मामले में के रूप में अन्य लोगों ने बताया है नहीं होगा) बनाया है, लेकिन यह कार्यक्रम धीमा काफी (मुझे लगता है कि यह 4 सेकंड ले लिया rt.jar के सभी पार्स करने के लिए किया था और है कि परिवर्तन रख दिया 8 सेकंड से अधिक)। उस समय में देख रहे थे (जेडीके 1.4 मुझे लगता है) इंटर्न() कोड बहुत बदसूरत और धीमा है कि शायद इसकी आवश्यकता है।

अगर मैं अपने कोड में इंटर्न() को कॉल करने पर विचार करना चाहता हूं तो मैं पहले इंटर्न के बिना इसे प्रोफाइल कर दूंगा() और फिर इसे स्मृति और गति दोनों के लिए इंटर्न() के साथ प्रोफाइल करें और देखें कि परिवर्तन के लिए कौन सा "बुरा" है।

+2

वाह ... और सटीक जानकारी के लिए नीचे वोट क्या थे? क्या जानकारी गलत है? – TofuBeer

+0

वास्तव में पीजीपी इस प्रश्न पर डाउनवॉट्स के साथ बहुत उदार था –

+2

मुझे नीचे वोटों की परवाह नहीं है ... सिर्फ उनके लिए कारण :-) – TofuBeer

0

मैंने "लॉकिंग" के लिए इंटर्न() का उपयोग किया है। उदाहरण के लिए, मान लें कि मेरे पास "व्यापार रिकॉर्ड" का "भंडार" है। जबकि मैं एक व्यापार को संपादित और अद्यतन करता हूं, मैं व्यापार को लॉक करना चाहता हूं; मैं बजाय व्यापार Id.intern() पर लॉक कर सकता हूं ताकि मुझे चारों ओर एक व्यापार के क्लोन के बारे में चिंता न करें। मुझे यकीन नहीं है कि हर कोई इस उपयोग को पसंद करता है।

मतलब यह है कि आईडी क्षेत्र गलती से किसी अन्य डोमेन वस्तु की आईडी क्षेत्र से टकराने की संभावना नहीं है - एक tradeId उदाहरण, के लिए ACCOUNT_NUMBER साथ टकराने से एक भी है, जहां कर रही हो सकता है ऐसा नहीं होता है

synchronized(account.getAccountNumber().intern()) {...} 

देखें example

+0

स्कैला के प्रतीक मूल रूप से String.intern() नहीं कर रहे हैं? –

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