जावा में एक वर्ग में (। जबकि) एक इंटरफ़ेस में .compareTo () क्यों है?


30

मैं जानना चाहता हूं कि इंटरफ़ेस .compareTo()में क्यों है Comparableजबकि क्लास .equalsमें एक तरीका है Object। मेरे लिए, यह मनमाना लगता है कि क्यों एक तरीका पहले से ही कक्षा .compareTo()में नहीं है Object

उपयोग करने के लिए .compareTo(), आप Comparableइंटरफ़ेस को लागू करते हैं और .compareTo()अपने उद्देश्यों के लिए विधि को लागू करते हैं। के लिए .equals()विधि, तो आप बस विधि अपनी कक्षा में, ओवरराइड के बाद से सभी वर्गों से विरासत Objectवर्ग।

मेरा प्रश्न यह है कि .compareTo()एक इंटरफ़ेस जैसा एक तरीका क्यों है जिसे आप एक वर्ग की बजाय लागू करते हैं Object? इसी तरह, .equals()क्लास में विधि क्यों लागू की जाती है Objectऔर कुछ इंटरफ़ेस में लागू नहीं किया जाता है?



2
यह जावा भाषा का एक डिज़ाइन विकल्प है (जरूरी नहीं कि यह सही विकल्प हो)। अन्य भाषाओं में, उदाहरण के लिए हास्केल , आपको मूल्य समानता प्राप्त करने के लिए समानता इंटरफ़ेस लागू करना होगा (वास्तव में आप Eqटाइपकास्ट के लिए एक उदाहरण प्रदान करते हैं )।
मल्लाहो

जवाबों:


58

सभी वस्तुओं की तुलना नहीं की जा सकती, लेकिन सभी वस्तुओं की समानता के लिए जाँच की जा सकती है। यदि और कुछ नहीं है, तो कोई यह देख सकता है कि स्मृति में दो वस्तुएं एक ही स्थान पर मौजूद हैं (संदर्भ समानता)।

compareTo()दो Threadवस्तुओं पर इसका क्या मतलब है ? एक धागा "दूसरे" से अधिक कैसे है? आप दो ArrayList<T>एस की तुलना कैसे करते हैं ?

Objectअनुबंध पर लागू होता है सब जावा वर्गों। अगर एक वर्ग की तुलना उसके स्वयं के वर्ग के अन्य उदाहरणों से Objectनहीं की जा सकती है , तो उसे इंटरफ़ेस का हिस्सा होने की आवश्यकता नहीं हो सकती है।

जोशुआ बलोच "प्राकृतिक क्रम" के प्रमुख शब्दों का उपयोग करते हुए बताते हैं कि एक वर्ग क्यों लागू करना चाहता है Comparable। जैसा कि ऊपर दिए गए मेरे उदाहरणों में उल्लेख किया गया है, हर वर्ग का स्वाभाविक आदेश नहीं है, इसलिए हर वर्ग को लागू नहीं करना चाहिए Comparableऔर न ही Objectइसका compareToतरीका होना चाहिए ।

... compareToविधि में घोषित नहीं किया गया है Object। ... यह करने के लिए चरित्र में समान है Objectके equalsविधि, सिवाय इसके कि यह सरल समानता तुलना के अलावा क्रम तुलना परमिट, और यह सामान्य है। लागू करने से Comparable, एक वर्ग इंगित करता है कि उसके उदाहरणों में एक प्राकृतिक आदेश है

प्रभावी जावा, दूसरा संस्करण : जोशुआ बलोच। आइटम 12, पृष्ठ 62। एलिप्स अन्य अध्यायों और कोड उदाहरणों के संदर्भ हटाते हैं।

ऐसे मामलों के लिए जहां आप एक गैर- वर्ग पर एक आदेश देना चाहते हैं जिसमें Comparableएक प्राकृतिक आदेश नहीं है, आप Comparatorइसे सॉर्ट करने में मदद करने के लिए हमेशा एक उदाहरण प्रदान कर सकते हैं ।


3
तब और भी मज़ा आता है जब आप एक्सेप्ट के साथ तुलना के बारे में सोचना शुरू करते हैं (जो कि एक अमूर्त वर्ग नहीं है और इस तरह इसे लागू किया होता है जिसका अर्थ है aNullPointerException.compareTo (aUnsupportedFlavorException) का अर्थ होगा

10
सभी वस्तुओं को जावा में समानता के लिए जांचा जा सकता है हां, लेकिन सामान्य तौर पर नहीं। वस्तुओं के कुछ उदाहरण हैं जहाँ समानता की तुलना का कोई मतलब नहीं है (संदर्भ समानता भी नहीं) - जैसे एकल। इसमें ValueEquality और ReferenceEquality जैसे इंटरफेस (अमूर्त वर्ग) हो सकते हैं। यह इतना बुरा विचार भी नहीं हो सकता है ...
15'15

5
"सभी वस्तुओं को समानता के लिए जांचा जा सकता है। यदि कुछ और नहीं, तो कोई देख सकता है कि स्मृति में दो वस्तुएं एक ही स्थान पर मौजूद हैं (संदर्भ समानता)।" - चूंकि हमारे पास ==बाद के लिए है, इसलिए इसमें एक खोखली अंगूठी है। निरर्थक डिफ़ॉल्ट की अवहेलना, सभी वर्गों पर ग्रहण करने के लिए एक वैध कारण मिल सकता है equals, क्योंकि सभी प्रकार एक समतुल्य संबंध का समर्थन नहीं कर सकते हैं।
राफेल

3
प्रकार के दो उदाहरण जहां यह समानता को परिभाषित करने के लिए समझदार नहीं है: धाराएं (जैसे आलसी संभावित अनंत सूचियां या अनंत सटीक संख्याएं) और कार्य। पूर्व में समस्या है कि समानता स्थापित करने के लिए असीम रूप से तुलना करने की आवश्यकता हो सकती है। यदि दो कार्य समान हैं, तो यह तय करना अनिर्दिष्ट है। यह पूछने पर कि क्या इस प्रकार के दो उदाहरण एक ही मेमोरी लोकेशन में मौजूद हैं 1) बहुत उपयोगी नहीं है और 2) क्लाइंट को कोड लिखने की अनुमति देता है जो कार्यान्वयन विवरणों के प्रति संवेदनशील है। आज मैं आपको हर बार पूछने पर उसी अनंत सूची का एक नया उदाहरण दे सकता हूं, कल मैं इसे याद कर सकता हूं।
डोभाल

6
@Snowman तथ्य यह है कि यह इस तथ्य के साथ संयुक्त है कि कार्यान्वयन के विवरण को उजागर करता है, यह अनुमति नहीं देने के लिए पर्याप्त कारण है। जावा 8 में बहुत अधिक हर "मूल्य-आधारित" वर्ग के पास कुछ बॉयलरप्लेट है जिसमें कहा गया है कि "यदि आप उपयोग करते हैं तो क्या होता है इसके लिए हम ज़िम्मेदार नहीं हैं ==" क्योंकि कैसे उन कक्षाओं को त्वरित रूप से लागू किया जाता है, लेकिन भाषा इसे छिपाना असंभव बनाती है। आप कह सकते हैं कि Integerसंदर्भ से दो एस की तुलना करने वाला कोई भी व्यक्ति एक बेवकूफ है, लेकिन तुलना शुरू करने की अनुमति देना अभी भी कम है।
डोभाल

8

JLS §4.3.2 को परिभाषित करता है classनिम्नलिखित तरीके से वस्तु:

4.3.2। द क्लास ऑब्जेक्ट

वर्ग Objectअन्य सभी वर्गों का एक सुपरक्लास (.18.1.4) है।

सभी वर्ग और सरणी प्रकार वंशानुक्रम (§8.4.8) वर्ग की विधियां हैं Object, जिन्हें संक्षेप में इस प्रकार है:

  • cloneकिसी वस्तु का डुप्लिकेट बनाने के लिए विधि का उपयोग किया जाता है।

  • विधि equalsवस्तु समानता की एक धारणा को परिभाषित करती है, जो मूल्य पर आधारित होती है, संदर्भ नहीं, तुलना।

  • finalizeकिसी वस्तु के नष्ट होने से ठीक पहले विधि को चलाया जाता है (run12.6)।

  • विधि getClassउस क्लास ऑब्जेक्ट को लौटाती है जो ऑब्जेक्ट के वर्ग का प्रतिनिधित्व करता है।

  • Classप्रत्येक संदर्भ प्रकार के लिए एक वस्तु मौजूद है। इसका उपयोग, उदाहरण के लिए, एक वर्ग के पूर्ण रूप से योग्य नाम, उसके सदस्यों, उसके तत्काल सुपरक्लास, और किसी भी इंटरफेस को खोजने के लिए किया जा सकता है जो इसे लागू करता है।

    एक विधि के आह्वान की अभिव्यक्ति का प्रकार getClassवह Class<? extends |T|>स्थान Tहै जहां वर्ग या इंटरफ़ेस खोजा गया है (.115.12.1) getClass

    एक वर्ग विधि जिसे घोषित किया गया है synchronized(.48.4.3.6) कक्षा के क्लास ऑब्जेक्ट से जुड़े मॉनिटर पर सिंक्रोनाइज़ करता है।

  • विधि hashCodeबहुत उपयोगी है, साथ में विधि बराबर होती है, जैसे हैशटैब में java.util.Hashmap

  • विधियों wait, notifyऔर notifyAllथ्रेड (,17.2) का उपयोग करके समवर्ती प्रोग्रामिंग में उपयोग किया जाता है।

  • विधि toStringऑब्जेक्ट का स्ट्रिंग प्रतिनिधित्व देता है।

तो, इसका कारण यही है equalsमें है Objectलेकिन compareToएक अलग इंटरफ़ेस में है। मैं अनुमान लगाऊंगा कि वे Objectयथासंभव न्यूनतम रखना चाहते थे । उन्होंने शायद यह अनुमान लगाया कि लगभग सभी Objects की आवश्यकता होगी equalsऔर hashCode(जो वास्तव में समानता परीक्षण का एक रूप है) लेकिन सभी वस्तुओं को ऑर्डर करने की अवधारणा की आवश्यकता नहीं होगी , जो कि इसके compareToलिए उपयोग किया जाता है।


मुझे लगता है कि सैद्धांतिक रूप से एक इंटरफ़ेस हो सकता है Equitable<T>लेकिन अगर Objectइसे लागू किया जाता है, तो हर वर्ग ए होगा Equitable<Object>। उस बिंदु पर, क्या कोई अंतर है? वास्तव में, वास्तव में जटिलता में नहीं।
कैप्टन मैन

1
@CaptainMan में नेट, objectहै Equals(object), बस जावा में की तरह है, लेकिन वहाँ भी है IEquatable<T>इंटरफ़ेस। हालांकि इसके मौजूद होने का प्राथमिक कारण Tमूल्य प्रकार होने पर मुक्केबाजी से बचना है, जो जावा में संभव नहीं है।
sv

हैशकोड समानता परीक्षण का एक रूप नहीं है, क्योंकि हैश टक्कर हैं। यदि A और B समान हैं, तो उनके पास समान हैशकोड है, लेकिन यदि A और B के पास समान हैशकोड है, इसका मतलब यह नहीं है कि वे समान हैं!
जोसेफ

वास्तव में, आपके जवाब से एक पुराने JLS ( titanium.cs.berkeley.edu/doc/java-langspec-1.0.pdf ) पर स्विच करने से बहुत लाभ होगा - यह सीधे equalsमें घोषित होने पर बहुत बेहतर उद्धरण है - जैसा कि जावा डिजाइन पीछे की ओर संगत है, जावा 1.0 डिजाइन विकल्प यह होने के लिए वास्तविक कारण है। ObjectThe methods equals and hashCode are declared for the benefit of hashtables such as java.util.Hashtable (§21.7)equals
vaxquis

चूंकि मेरे द्वारा प्रस्तावित किया गया संपादन संभवत: "बहुत अधिक कठोर" होने के कारण अस्वीकृत हो जाएगा, यदि आप अपने जवाब में प्रासंगिक सामान Ctrl + C / Ctrl + V चाहते हैं: pastebin.com/8c4EpLRX
vaxquis

2

स्नोमैन के उत्कृष्ट उत्तर के अलावा, याद रखें कि Comparableलंबे समय से एक सामान्य इंटरफ़ेस रहा है। एक प्रकार लागू नहीं होता है compareTo(object), यह लागू होता है compareTo(T)जहां Tइसका अपना प्रकार है। इसे लागू नहीं किया जा सकता है object, क्योंकि objectयह उस वर्ग को नहीं जानता है जो इससे उत्पन्न होगा।

objectएक compareTo(object)विधि को परिभाषित कर सकता था , लेकिन इसने स्नोमैन को केवल दो ArrayList<T>एस या दो के बीच तुलना की अनुमति नहीं दीThread , बल्कि ए ArrayList<T>और ए के बीच तुलनाThread । वह और भी निरर्थक है।


0

मान लीजिए कि मेरे पास दो वस्तु संदर्भ हैं: X एक उदाहरण की पहचान करता है String सामग्री "जॉर्ज" रखने की ; Y Pointनिर्देशांक [12,34] को धारण करने के उदाहरण की पहचान करता है । निम्नलिखित दो प्रश्नों पर विचार करें:

  • क्या X और Y समतुल्य वस्तुओं की पहचान करते हैं?

  • क्या X को पहले, बाद में या Y के समतुल्य होना चाहिए?

तथ्य यह है कि एक्स और वाई असंबंधित प्रकार के उदाहरणों की पहचान करते हैं, पहले प्रश्न पर विचार करते समय कोई समस्या नहीं होती है। वस्तुओं को केवल तभी समतुल्य माना जा सकता है जब उनके प्रकार एक समान आधार साझा करते हैं जो उन्हें समतुल्य होने के रूप में परिभाषित करता है; चूंकि Stringऔर Pointऐसा कोई आधार नहीं है (उनका एकमात्र सामान्य आधार सभी विशिष्ट वस्तुओं को गैर-समतुल्य मानता है) इसका उत्तर बस "नहीं" है।

तथ्य यह है कि प्रकार असंबंधित हैं, हालांकि, दूसरे प्रश्न के संबंध में एक बड़ी समस्या है। कुछ प्रकार उनके उदाहरणों के बीच आदेश देने वाले संबंधों को परिभाषित करते हैं, और कुछ आदेश देने वाले रिश्ते कई प्रकारों पर भी विस्तारित हो सकते हैं [जैसे कि यह संभव है BigIntegerऔर एक के लिए, लेकिन अधिकांश छंटाई एल्गोरिदम को कुल आदेशों की आवश्यकता होती है। इस प्रकार, यहां तक ​​कि अगर सभी ऑब्जेक्ट एक विधि को लागू कर सकते हैं यदि "अनट्रेंड" एक वैध रिटर्न था, तो इस तरह की विधि इसके अस्तित्व को सही ठहराने के लिए पर्याप्त उपयोगी नहीं होगी।BigDecimal तुलना विधियों को परिभाषित करने के लिए जो दोनों प्रकार के उदाहरणों को दूसरे के उदाहरणों के सापेक्ष रैंक करने की अनुमति देगा], लेकिन सामान्य रूप से दो मनमाना उदाहरण लेना संभव नहीं है और "पहले एक्स को सॉर्ट करना चाहिए, बाद में, या वाई के बराबर" और कुल ऑर्डर प्राप्त करना चाहिए। यह पूछना संभव होगा कि "क्या X को पहले, बाद, समकक्ष, या Y के संबंध में असंबद्ध होना चाहिए" यदि वस्तुओं को एक सुसंगत आदेश की रिपोर्ट करना आवश्यक था, हालांकि कुल नहीं।compareTo

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.