2009-02-06 28 views
72

जावा में एक enum Comparable इंटरफ़ेस लागू करता है। Comparable की compareTo विधि को ओवरराइड करना अच्छा होगा, लेकिन यहां इसे अंतिम के रूप में चिह्नित किया गया है। Enum के compareTo पर डिफ़ॉल्ट प्राकृतिक क्रम सूचीबद्ध क्रम है।जावा में एनम फाइनल पर तुलना करने की तुलना क्यों की जाती है?

क्या किसी को पता है कि जावा एनम्स के पास यह प्रतिबंध क्यों है?

उत्तर

98

स्थिरता के लिए मुझे लगता है कि ... जब आप एक enum प्रकार देखते हैं, आप एक तथ्य कि अपनी प्राकृतिक आदेश जिस क्रम में स्थिरांक की घोषणा की जाती है के लिए पता

इस समाधान के लिए, आप आसानी से अपने खुद Comparator<MyEnum> बना सकते हैं और इसका इस्तेमाल जब भी आप एक अलग आदेश की जरूरत है सकते हैं:

MyEnumComparator c = new MyEnumComparator(); 
int order = c.compare(MyEnum.CAT, MyEnum.DOG); 

या में इसका इस्तेमाल करते हैं:

enum MyEnum 
{ 
    DOG("woof"), 
    CAT("meow"); 

    String sound;  
    MyEnum(String s) { sound = s; } 
} 

class MyEnumComparator implements Comparator<MyEnum> 
{ 
    public int compare(MyEnum o1, MyEnum o2) 
    { 
     return -o1.compareTo(o2); // this flips the order 
     return o1.sound.length() - o2.sound.length(); // this compares length 
    } 
} 

आप Comparator सीधे उपयोग कर सकते हैं संग्रह या सरणी:

NavigableSet<MyEnum> set = new TreeSet<MyEnum>(c); 
MyEnum[] array = MyEnum.values(); 
Arrays.sort(array, c);  

फर्थ एर जानकारी:

+0

कस्टम तुलनाकर्ता एक संग्रह में एनम की आपूर्ति करते समय केवल वास्तव में प्रभावी होते हैं। यदि आप प्रत्यक्ष तुलना करना चाहते हैं तो इससे ज्यादा मदद नहीं मिलती है। –

+5

हाँ, यह करता है। नया MyEnumComparator.compare (enum1, enum2)। और voilá। – Bombe

+0

@ मार्टिनोकोनर और बॉम्बे: मैंने आपकी टिप्पणियों को उत्तर में शामिल किया है। धन्यवाद! –

-2

यदि आप अपने enum के तत्वों का प्राकृतिक क्रम बदलना चाहते हैं, तो स्रोत कोड में अपना ऑर्डर बदलें।

+0

यूप, मैंने मूल प्रविष्टि में लिखा है :) – neu242

+0

हाँ, लेकिन आप वास्तव में यह नहीं समझाते कि आप तुलना करने के लिए क्यों ओवरराइड करना चाहते हैं()। तो मेरा निष्कर्ष यह था कि आप कुछ बुरा करने की कोशिश कर रहे हैं और मैं आपको एक और सही तरीका दिखाने की कोशिश कर रहा था। – Bombe

+0

मुझे नहीं पता कि मुझे हाथों से प्रविष्टियों को सॉर्ट करना क्यों चाहिए जब कंप्यूटर मुझसे ज्यादा बेहतर होता है। – neu242

5

गणन मान ठीक क्रम में वे घोषित किया गया है के अनुसार तार्किक आदेश दिया जाता है। यह जावा भाषा विनिर्देश का हिस्सा है। इसलिए यह इस प्रकार है कि गणना मूल्यों की तुलना केवल तभी की जा सकती है जब वे एक ही एनम के सदस्य हों। विनिर्देश आगे यह गारंटी देना चाहता है कि तुलना करने के लिए तुलनीय तुलनीय आदेश() द्वारा क्रमबद्ध किया गया है जिस क्रम में मूल्य घोषित किए गए थे। यह एक गणना की परिभाषा है।

+0

जैसा कि थॉमस Paine ने अपने उदाहरण में स्पष्ट किया, भाषा केवल वाक्य रचनाओं द्वारा आदेश दे सकता है, अर्थशास्त्र नहीं। आप कहते हैं, आइटम _ordered_ तर्कसंगत हैं, लेकिन जिस तरह से मैं enum समझता हूं, आइटम तार्किक माध्यम से _encapsulated_ हैं। – Bondax

28

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


    //===== SI BYTES (10^n) =====// 

    /** 1,000 bytes. */ KILOBYTE (false, true, 3, "kB"), 
    /** 106 bytes. */ MEGABYTE (false, true, 6, "MB"), 
    /** 109 bytes. */ GIGABYTE (false, true, 9, "GB"), 
    /** 1012 bytes. */ TERABYTE (false, true, 12, "TB"), 
    /** 1015 bytes. */ PETABYTE (false, true, 15, "PB"), 
    /** 1018 bytes. */ EXABYTE (false, true, 18, "EB"), 
    /** 1021 bytes. */ ZETTABYTE(false, true, 21, "ZB"), 
    /** 1024 bytes. */ YOTTABYTE(false, true, 24, "YB"), 

    //===== IEC BYTES (2^n) =====// 

    /** 1,024 bytes. */ KIBIBYTE(false, false, 10, "KiB"), 
    /** 220 bytes. */ MEBIBYTE(false, false, 20, "MiB"), 
    /** 230 bytes. */ GIBIBYTE(false, false, 30, "GiB"), 
    /** 240 bytes. */ TEBIBYTE(false, false, 40, "TiB"), 
    /** 250 bytes. */ PEBIBYTE(false, false, 50, "PiB"), 
    /** 260 bytes. */ EXBIBYTE(false, false, 60, "EiB"), 
    /** 270 bytes. */ ZEBIBYTE(false, false, 70, "ZiB"), 
    /** 280 bytes. */ YOBIBYTE(false, false, 80, "YiB"); 

ऊपर आदेश स्रोत कोड में अच्छा लग रहा है, लेकिन कैसे नहीं लेखक का मानना ​​है कि compareTo काम करना चाहिए है। वांछित तुलना व्यवहार के लिए बाइट्स की संख्या के अनुसार आदेश है। स्रोत-कोड ऑर्डरिंग जो ऐसा करेगा, कोड के संगठन को खराब कर देगा।

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

+3

सहमत हैं, मैं चाहता हूं कि मेरा enum एक ऑर्डर के बजाय एक व्यापार तुलनीय अल्गोरिथम प्राप्त करने में सक्षम हो, जो किसी को ध्यान न दे तो टूटा जा सकता है। – TheBakker

2

एक संभावित स्पष्टीकरण यह है कि compareToequals के साथ संगत होना चाहिए।

और equals enums के लिए पहचान समानता (==) के अनुरूप होना चाहिए।

यदि compareTo जहां गैर-फाइनल होना है तो इसे एक व्यवहार के साथ ओवरराइड करना संभव होगा जो equals के अनुरूप नहीं था, जो बहुत ही अंतर्ज्ञानी होगा।

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