स्ट्रिंग क्लास + ऑपरेटर को कैसे ओवरराइड करता है?


129

जावा में क्यों आप स्ट्रिंग को + ऑपरेटर के साथ जोड़ सकते हैं, जब स्ट्रिंग एक वर्ग है? में String.javaकोड मैं इस ऑपरेटर के लिए किसी भी कार्यान्वयन नहीं मिला। क्या यह अवधारणा वस्तु अभिविन्यास का उल्लंघन करती है?


21
प्लस ( +) ऑपरेटर जावा की भाषा सुविधा है।
adatapost

18
यह सब कंपाइलर का जादू है। आप जावा में ऑपरेटर ओवरलोडिंग नहीं कर सकते।
लॉयन

18
मुझे लगता है कि अजीब बात यह है कि स्ट्रिंग को भाषा के बाहर एक पुस्तकालय के रूप में लागू किया जाता है (java.lang.String में), फिर भी भाषा के अंदर इसका विशिष्ट समर्थन है । यह सही नहीं है।
13ren


@ 13ren तुम गलत हो। स्ट्रिंग java.lang वर्ग के अलावा है जो भाषा के लिए खड़ा है - जावा lanaguage !!! इस पैकेज की सभी कक्षाएं विशेष हैं। ध्यान दें कि आपको उन्हें उपयोग करने के लिए java.lang आयात करने की आवश्यकता नहीं है।

जवाबों:


156

आइए जावा में निम्नलिखित सरल भावों को देखें

int x=15;
String temp="x = "+x;

कंपाइलर आंतरिक रूप से परिवर्तित हो "x = "+x;जाता है StringBuilderऔर .append(int)स्ट्रिंग में पूर्णांक को "जोड़ने" के लिए उपयोग करता है।

5.1.11। स्ट्रिंग रूपांतरण

स्ट्रिंग रूपांतरण द्वारा किसी भी प्रकार को स्ट्रिंग में बदला जा सकता है।

आदिम प्रकार टी का एक मान x पहले संदर्भ मान में परिवर्तित किया जाता है जैसे कि एक उपयुक्त वर्ग उदाहरण सृजन अभिव्यक्ति (expression15.9) के तर्क के रूप में देकर:

  • यदि टी बुलियन है, तो नए बुलियन (एक्स) का उपयोग करें।
  • यदि T चार है, तो नए वर्ण (x) का उपयोग करें।
  • यदि टी बाइट, शॉर्ट या इंट है, तो नए इंटेगर (एक्स) का उपयोग करें।
  • यदि T लंबा है, तो नए Long (x) का उपयोग करें।
  • यदि टी फ्लोट है, तो नए फ्लोट (x) का उपयोग करें।
  • यदि T डबल है, तो नए डबल (x) का उपयोग करें।

यह संदर्भ मान स्ट्रिंग स्ट्रिंग द्वारा टाइपिंग में कनवर्ट किया जाता है।

अब केवल संदर्भ मूल्यों पर विचार करने की आवश्यकता है:

  • यदि संदर्भ शून्य है, तो इसे स्ट्रिंग "null" (चार ASCII वर्ण n, u, l, l) में बदल दिया जाता है।
  • अन्यथा, रूपांतरण ऐसे किया जाता है जैसे कि बिना किसी दलील के संदर्भित वस्तु के स्ट्रेचिंग विधि के आह्वान के द्वारा; लेकिन अगर स्टोस्ट्रिंग विधि को लागू करने का परिणाम शून्य है, तो इसके बजाय स्ट्रिंग "नल" का उपयोग किया जाता है।

TheString पद्धति को प्राइमर्ड क्लास ऑब्जेक्ट (.24.3.2) द्वारा परिभाषित किया गया है। कई वर्ग इसे ओवरराइड करते हैं, विशेष रूप से बूलियन, कैरेक्टर, इंटेगर, लॉन्ग, फ्लोट, डबल और स्ट्रिंग।

स्ट्रिंग रूपांतरण संदर्भ के विवरण के लिए for5.4 देखें।

15.18.1।

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

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

अनुकूलित संस्करण वास्तव में एक पूर्ण लपेटा हुआ स्ट्रिंग रूपांतरण पहले नहीं करेगा।

यह संकलक द्वारा उपयोग किए गए अनुकूलित संस्करण का एक अच्छा चित्रण है, यद्यपि एक आदिम के रूपांतरण के बिना, जहां आप संकलक को चीजों को पृष्ठभूमि में स्ट्रिंगबर्ल में बदलते देख सकते हैं:

http://caprazzi.net/posts/java-bytecode-string-concatenation-and-stringbuilder/


यह जावा कोड:

public static void main(String[] args) {
    String cip = "cip";
    String ciop = "ciop";
    String plus = cip + ciop;
    String build = new StringBuilder(cip).append(ciop).toString();
}

इसे उत्पन्न करता है - देखें कि कैसे दो संयोजन शैली एक ही बाइटकोड को जन्म देती हैं:

 L0
    LINENUMBER 23 L0
    LDC "cip"
    ASTORE 1
   L1
    LINENUMBER 24 L1
    LDC "ciop"
    ASTORE 2

   // cip + ciop

   L2
    LINENUMBER 25 L2

    NEW java/lang/StringBuilder
    DUP
    ALOAD 1
    INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
    INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    ALOAD 2
    INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;

    ASTORE 3

    // new StringBuilder(cip).append(ciop).toString()

   L3
    LINENUMBER 26 L3

    NEW java/lang/StringBuilder
    DUP
    ALOAD 1
    INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
    ALOAD 2
    INVOKEVIRTUAL java/lang/StringBuilder.append(Ljava/lang/String;)Ljava/lang/StringBuilder;
    INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;

    ASTORE 4
   L4
    LINENUMBER 27 L4
    RETURN

ऊपर दिए गए उदाहरण को देखते हुए और दिए गए उदाहरण में स्रोत कोड के आधार पर बाइट कोड कैसे उत्पन्न होता है, आप यह नोटिस कर पाएंगे कि संकलक ने आंतरिक रूप से निम्नलिखित कथन को बदल दिया है

cip+ciop; 

में

new StringBuilder(cip).append(ciop).toString();

दूसरे शब्दों में, +स्ट्रिंग कंसट्रक्शन में ऑपरेटर अधिक क्रिया StringBuilderमुहावरे के लिए प्रभावी रूप से आशुलिपि है ।


3
बहुत बहुत धन्यवाद, मैं jvm बाइट कोड से परिचित नहीं हूँ लेकिन स्ट्रिंग प्लस = cip + ciop के लिए उत्पन्न कोड; और स्ट्रिंग का निर्माण = नया StringBuilder (cip) .append (ciop) .toString (); समान हैं। और मेरा सवाल यह है कि क्या यह ऑपरेशन ऑब्जेक्ट ओरिएंटेशन का उल्लंघन करता है?
पूया

7
नहीं, यह नहीं है। ऑपरेटर ओवरलोडिंग (सी ++ और कुछ भाषाओं में) में कुछ कमियां हैं और जावा डिजाइनरों ने महसूस किया कि यह कुछ हद तक एक भ्रामक अवधारणा है और इसे जावा से हटा दिया गया है। मेरे लिए, एक ऑब्जेक्ट-ओरिएंटेड भाषा में वंशानुक्रम, बहुरूपता और एनकैप्सुलेशन की प्रमुख अवधारणाएँ होनी चाहिए जो कि जावा के पास है।
लॉयन

2
हां, लेकिन मुझे लगता है कि इस ऑपरेटर ने स्ट्रिंग क्लास
पूया

3
हां, स्ट्रिंग में टाइप करने की क्रिया के लिए ऑपरेटर ओवरलोडिंग का उपयोग जावा में किया जाता है, हालांकि, आप अपने स्वयं के ऑपरेटर को परिभाषित नहीं कर सकते हैं (जैसा कि C ++, C # और कुछ अन्य भाषाओं में)।
लायन

5
@Pooya: वास्तव में "int / int" बनाम "int / float" पहले से ही ऑपरेटर ओवरलोडिंग है, इसलिए C के पास भी है। क्या सी (और जावा) हालांकि नहीं है है उपयोगकर्ता परिभाषित ऑपरेटर ओवरलोडिंग है: केवल बात यह है कि परिभाषित करता है अलग अलग तरीकों से (दोनों सी और जावा में) एक ऑपरेटर इस्तेमाल किया जा सकता भाषा परिभाषा है (और भेद में कार्यान्वित किया जाता है संकलक)। C ++ इसमें भिन्न है कि यह उपयोगकर्ता-परिभाषित ऑपरेटर को ओवरलोडिंग की अनुमति देता है (जिसे अक्सर "ऑपरेटर ओवरलोडिंग" के रूप में संदर्भित किया जाता है)।
Joachim Sauer

27

यह जावा संकलक सुविधा है जो +ऑपरेटर के संचालन की जांच करती है । और ऑपरेंड के आधार पर यह बाइट कोड उत्पन्न करता है:

  • स्ट्रिंग के लिए, यह कॉन्ट्रास्ट स्ट्रिंग्स के लिए कोड उत्पन्न करता है
  • संख्याओं के लिए, यह संख्याओं को जोड़ने के लिए कोड उत्पन्न करता है।

यह जावा कल्पना क्या कहती है :

ऑपरेटर + -को एडिटिव ऑपरेटर कहा जाता है। AdditiveExpression: MultiplicativeExpression AdditiveExpression + MultiplicativeExpression AdditiveExpression - गुणात्मकExpression

योजक संचालकों की एक ही पूर्वता होती है और वे वाक्यात्मक रूप से बाएं सहयोगी होते हैं (वे समूह बाएं से दाएं)। यदि किसी +ऑपरेटर के किसी भी प्रकार का प्रकार है String, तो ऑपरेशन स्ट्रिंग समवर्ती है।

अन्यथा, +ऑपरेटर के प्रत्येक प्रकार का प्रकार एक प्रकार होना चाहिए जो कि एक आदिम संख्यात्मक प्रकार के लिए परिवर्तनीय (§5.1.8) है, या एक संकलन-समय त्रुटि उत्पन्न होती है।

प्रत्येक मामले में, बाइनरी -ऑपरेटर के प्रत्येक ऑपरेंड का प्रकार एक प्रकार होना चाहिए जो कि एक आदिम संख्यात्मक प्रकार के लिए परिवर्तनीय (to5.1.8) है, या एक संकलन-समय त्रुटि उत्पन्न होती है।


7
कल्पना से उद्धरण इस प्रश्न के लिए बिल्कुल भी प्रासंगिक नहीं है।
अर्नेस्ट फ्रेडमैन-हिल

यह एक्स्ट्रेक्ट है "यदि किसी ऑपरेटर का प्रकार किसी + ऑपरेटर का स्ट्रिंग है, तो ऑपरेशन स्ट्रिंग कॉनटेनैशन है। अन्यथा, ऑपरेटर के प्रत्येक ऑपरेंड का प्रकार एक प्रकार होना चाहिए जो परिवर्तनीय हो (.15.8.8) ) एक आदिम संख्यात्मक प्रकार के लिए, या एक संकलन-समय त्रुटि उत्पन्न होती है "। क्या आप मुझे बता सकते हैं कि यह प्रासंगिक क्यों नहीं है।
रमेश PVK

7
यह कैसे लागू होता है, इस बारे में कुछ भी नहीं कहता है, जो कि सवाल है। मुझे लगता है कि पोस्टर पहले से ही समझते हैं कि सुविधा मौजूद है।
अर्नेस्ट फ्राइडमैन-हिल

14

कैसे स्ट्रिंग वर्ग ओवरराइड करता है + ऑपरेटर?

यह नहीं है संकलक करता है। कड़ाई से बोलते हुए, कंपाइलर स्ट्रिंग ऑपरेंड के लिए + ऑपरेटर को ओवरलोड करता है।


6

सबसे पहले (+) अतिभारित नहीं है

जावा लैंग्वेज स्ट्रिंग कॉन्फ्रेक्शन ऑपरेटर (+) के लिए विशेष सहायता प्रदान करता है, जिसे जावा स्ट्रिंग्स ऑब्जेक्ट्स के लिए अतिभारित किया गया है।

  1. यदि बाएं हाथ का ऑपरेशन स्ट्रिंग है, तो यह संघनन का काम करता है।

  2. यदि लेफ्ट हैंड साइड ऑपरेंड है तो यह इंटेगर है जो अतिरिक्त ऑपरेटर के रूप में काम करता है


3
(२) यदि बाएं ऑपेरैंड एक इंटेगर है तो यह ऑटो-अनबॉक्स है intऔर फिर जावा के सामान्य नियम लागू होते हैं।
लोर्न

2
उद्धरण के नीचे दिए गए दो नियम गलत हैं: मेरा मानना ​​है कि उन्हें होना चाहिए: दो आदिम (या अनबॉक्सेबल क्लासेस) = जोड़; कम से कम एक स्ट्रिंग =
संघनन

4

जावा लैंग्वेज स्ट्रिंग कॉन्फिनेशन ऑपरेटर (+) और अन्य ऑब्जेक्ट्स को स्ट्रिंग्स में बदलने के लिए विशेष सहायता प्रदान करता है। स्ट्रिंग संघन को StringBuilder(या StringBuffer) वर्ग और उसकी appendविधि के माध्यम से कार्यान्वित किया जाता है ।


4

+लागू होने पर ऑपरेटर का अर्थ Stringभाषा द्वारा परिभाषित किया गया है, जैसा कि सभी ने पहले ही लिखा है। चूंकि आपको यह पर्याप्त रूप से समझाने योग्य नहीं लगता है, इस पर विचार करें:

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

तो, सिद्धांत रूप में, "जोड़" वस्तुओं की प्रकृति पर निर्भर करता है "जोड़ा"। जावा स्ट्रिंग्स के साथ-साथ इन्ट्स और फ्लोट्स (लॉन्ग, डबल्स, ...) के लिए इसे परिभाषित करता है।


3

+ऑपरेटर आम तौर पर एक की जगह StringBuilderसंकलन समय पर। उस मामले पर अधिक जानकारी के लिए इस उत्तर को जांचें ।


यदि यह मामला है, तो क्या कोई कारण है कि StringBuilder सार्वजनिक उपयोग के लिए बिल्कुल मौजूद है? क्या ऐसे कोई मामले हैं जहां +ऑपरेटर को प्रतिस्थापित नहीं किया गया है StringBuilder?
केमरे

2
आप जो प्रश्न पूछना चाहते हैं, वह यह है कि "सार्वजनिक उपयोग के लिए + ऑपरेटर क्यों मौजूद है?", क्योंकि यहाँ घृणा है। आपके अन्य प्रश्न के रूप में, मैं इसे ठीक से नहीं जानता, लेकिन मुझे लगता है कि ऐसा कोई मामला नहीं है।
वृश्चिक

कंपाइलर कॉनैट का उपयोग कर सकते हैं (), बजाय अगर दो तत्व हैं। जब कंपाइलर स्ट्रिंगब्यूलर के साथ कॉनैट () का उपयोग करने में विफल रहता है (या कई स्ट्रिंगरबिल्डर्स का उपयोग करता है और उन्हें एक साथ जोड़ देता है) जब प्रोग्रामर लंबे नेस्टेड / लूप कोड में स्ट्रिंग का निर्माण कर रहा है - एकल, स्पष्ट स्ट्रिंगब्यूलर का उपयोग प्रदर्शन के लिए बेहतर होगा।
user158037
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.