2012-01-31 9 views
8

मुझे हाल ही में काम पर हमारे कोडबेस में यह छोटा मणि मिला। बस बुला MysteryEnum.values() यह sun.misc.SharedSecret बुलाया कुछ का उपयोग कर रहा है के बजायsun.misc. का उपयोग किया गया शेयर

package foo.bar; 

import sun.misc.SharedSecrets; 
import foo.baz.HasAGetValuesMethod; 

public enum MysteryEnum implements HasAGetValuesMethod { 

    THINGY, BOB; 

    @Override 
    public MysteryEnum[] getValues() { 
     return SharedSecrets.getJavaLangAccess().getEnumConstantsShared(MysteryEnum .class); 
    } 
} 

getValues ​​में() विधि: मैं कबूल करने के लिए मैं बिल्कुल पता नहीं क्यों इस enum इस तरह से लिखा गया था कि है (नाम मासूम की रक्षा करने के लिए बदल) sun.misc.JavaLangAccess नामक किसी चीज़ को संभालने के लिए, फिर का उपयोग करके सभी enum मानों की सरणी प्राप्त करने के लिए। उस वर्ग पर जावाडोक आपको बताता है कि विधि क्या करती है, लेकिन मुझे पर पर अधिक नहीं मिल रहा है, आप इसे कॉल करना चाहते हैं।

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

उत्तर

7

विधि प्रतिबिंब के बिना एक ही सरणी देता है या अंतर्निहित सरणी की प्रतिलिपि/क्लोनिंग करता है। यह प्रदर्शन में सुधार करता है, लेकिन एक म्यूटेबल सरणी का खुलासा करने के लिए एक अच्छा विचार नहीं है।

for (int i = 0; i < 3; i++) 
    System.out.println(SharedSecrets.getJavaLangAccess().getEnumConstantsShared(AccessMode.class)); 
AccessMode[] ams = SharedSecrets.getJavaLangAccess().getEnumConstantsShared(AccessMode.class); 
ams[1] = ams[2]; // don't do this !! 
System.out.println(EnumSet.allOf(AccessMode.class)); 

प्रिंट

[Ljava.nio.file.AccessMode;@330cdec1 
[Ljava.nio.file.AccessMode;@330cdec1 
[Ljava.nio.file.AccessMode;@330cdec1 
[READ, EXECUTE, EXECUTE] 

के बजाय इस पद्धति का उपयोग, मैं क्या का उपयोग अपने ही कैश की गई प्रतिलिपि

// cannot be modified. 
private static final AccessMode[] ACCESS_MODES = AccessMode.values(); 
+0

मैं देखता हूं। तो यह एक प्रदर्शन हैक है। इसके दिखने से, काफी भंगुर है। – Jon

+0

पर्याप्त इसकी अस्पष्ट, 'सूर्य के नीचे। *', कि आप इसे से बचने या बड़ी सावधानी से संभाल करने के लिए पता होना चाहिए। 'Sun.misc.Unsafe' के समान;) –

+0

के बारे में शिकार होने के बाद - यह मान() विधि वास्तव में संकलक द्वारा जोड़ा जाता है (यह Enum के लिए जावाडोक पर नहीं है) की तरह दिखता है। यदि ऐसा है, तो हम कैसे सुनिश्चित कर सकते हैं कि उपर्युक्त किसी भी तरह से अनुकूलित भी है? शायद संकलक को एक ही सरणी में एक हैंडल वापस करने के लिए अनुकूलित किया जाता है जहां मूल्य कहा जाता है? क्या यह जांचने का कोई तरीका है? – Jon

3
मूल रूप से SharedSecret

:

"साझा रहस्य" है, जो प्रतिबिंब का उपयोग किए बिना एक और पैकेज में कार्यान्वयन-निजी तरीकों बुला के लिए एक तंत्र हैं का एक भंडार।

कोड वर्ग पढ़ने और स्थिरांक वापस लौटने (प्रतिबिंब कॉल नहीं करना पड़ता) द्वारा enum स्थिरांक देता है। यह एक तरह से गतिशील है कि अगर एनम में एक नया enum स्थिर जोड़ा जाता है, तो getValues() विधि अतिरिक्त enums वापस लौटाएगी (पूरे शो में कोड बदलने की आवश्यकता नहीं है)।

+0

मैं इसे नहीं मिलता है। यदि आप आगे enum मान जोड़ते हैं, तो मूल्यों को कॉल करें() आपको मूल के साथ अतिरिक्त enums भी मिलते हैं। क्या प्राप्त होता है वैल्यूज(), जैसा कि लागू किया गया है, आपको ऊपर देता है? – Jon

+0

यह सिर्फ सटीक, मूल मान वापस लौटाता है (क्लोनिंग या कैशिंग की आवश्यकता के बिना)। असल में, यह जेवीएम स्टैक को छोड़कर और प्रत्यक्ष मूल्य प्राप्त करने का एक तरीका है। –

1

documentation का कहना है:

रिटर्न एक enum वर्ग के तत्वों या अशक्त वर्ग वस्तु एक enum प्रकार का प्रतिनिधित्व नहीं करता है; परिणाम सभी कॉलर्स द्वारा अनधिकृत, कैश किया गया है, और साझा किया गया है।

तो, जब तक कि बिंदु, एक साझा सरणी प्रदान करने के लिए इतना है कि किसी को भी अशक्त करने के लिए अपने तत्वों में से एक को सेट करके या छँटाई यह द्वारा सब कुछ टूट सकता था, या जो कुछ भी (जिनमें से परिणाम को संचित करने से किया जा सकता था values() विधि), मेरा अनुमान यह भी है कि यह लाइन पिछले डेवलपर की अक्षमता के कारण है।

मैं एक यूनिट परीक्षण लिखूंगा, फिर इसे values() पर कॉल के साथ प्रतिस्थापित करें और जांचें कि यूनिट परीक्षण अभी भी गुजरता है।

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