जावा के + =, - =, * =, / = यौगिक असाइनमेंट ऑपरेटरों को कास्टिंग की आवश्यकता क्यों नहीं है?


3633

आज तक, मैंने सोचा था कि उदाहरण के लिए:

i += j;

के लिए सिर्फ एक शॉर्टकट था:

i = i + j;

लेकिन अगर हम यह कोशिश करें:

int i = 5;
long j = 8;

फिर i = i + j;संकलन नहीं i += j;करेगा बल्कि जुर्माना संकलित करेगा।

क्या इसका मतलब यह है कि वास्तव i += j;में इस तरह से कुछ के लिए एक शॉर्टकट है i = (type of i) (i + j)?


135
मुझे आश्चर्य है कि जावा इसकी अनुमति देता है, अपने पूर्ववर्तियों की तुलना में एक कठोर भाषा है। कास्टिंग में त्रुटियां गंभीर विफलता का कारण बन सकती हैं, जैसा कि एरिएन 5 फ्लाइट 501 के साथ हुआ था, जहां 64-बिट फ्लोट के लिए 16-बिट पूर्णांक का निर्माण दुर्घटना में हुआ था।
SQLDiver

103
जावा में लिखे गए उड़ान नियंत्रण प्रणाली में, यह आपकी चिंताओं से कम से कम होगा @SQLDiver
रॉस ड्रू

10
वास्तव में i+=(long)j;भी ठीक संकलन होगा।
थारिंदु सत्तीचंद्र

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

5
यदि इसे कास्टिंग की आवश्यकता होती है, तो आप इसे कहां रखेंगे? i += (int) f;इसके अलावा, पहले के मुकाबले च (int) i += f;असाइनमेंट के बाद परिणाम कास्ट करता है, न के बराबर। ऐसी कोई जगह नहीं होगी जिसमें एक डाली डाली जाए जो यह दर्शाता है कि आप मूल्य जोड़ना चाहते हैं, लेकिन असाइनमेंट से पहले।
नॉरिल टेम्पेस्ट

जवाबों:


2441

हमेशा इन सवालों के साथ, JLS उत्तर रखता है। इस मामले में this15.26.2 कंपाउंड असाइनमेंट ऑपरेटर हैं । निष्कर्ष:

प्रपत्र E1 op= E2का एक मिश्रित असाइनमेंट अभिव्यक्ति के बराबर है E1 = (T)((E1) op (E2)), जहां Tप्रकार है E1, सिवाय इसके कि E1केवल एक बार मूल्यांकन किया जाता है।

§15.26.2 से उद्धृत एक उदाहरण

[...] निम्नलिखित कोड सही है:

short x = 3;
x += 4.6;

और x में परिणाम 7 का मान है क्योंकि यह इसके बराबर है:

short x = 3;
x = (short)(x + 4.6);

दूसरे शब्दों में, आपकी धारणा सही है।


42
इसलिए i+=jसंकलन करता है जैसा कि मैंने खुद को जांचा, लेकिन इससे सटीक नुकसान होगा? अगर ऐसा है, तो यह i = i + j में भी ऐसा करने की अनुमति क्यों नहीं देता है? हमें वहाँ क्यों?
bad_keypoint

46
@ronnieaka: मैं अनुमान लगा रहा हूं कि भाषा डिजाइनरों ने महसूस किया कि एक मामले में ( i += j), यह मान लेना सुरक्षित है कि सटीकता का नुकसान अन्य मामले के विपरीत वांछित है ( i = i + j)
लुकास एडर

12
नहीं, इसका अधिकार वहीं है, मेरे लिए! क्षमा करें, मैंने इसे पहले नहीं देखा था। जैसा कि आपके उत्तर में है E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), इसलिए इसका प्रकार है टाइपकास्ट नीचे टाइप करना (लंबे समय से अंत तक नीचे)। जबकि में मैं मैं + जे =, हम यह स्पष्ट रूप से ऐसा करने के लिए, यानी, प्रदान की है (T)में भाग E1 = ((E1) op (E2))नहीं है, यह?
bad_keypoint 14

11
जावा कंपाइलर टाइपकास्ट करने के लिए एक संभावित कारण यह है कि अगर आप असंगत प्रकारों पर अंकगणित करने की कोशिश कर रहे हैं, तो अनुबंधित फॉर्म का उपयोग करके परिणाम का टाइपकास्ट करने का कोई तरीका नहीं है। परिणाम का टाइपकास्ट आम तौर पर समस्याग्रस्त तर्क के टाइपकास्ट से अधिक सटीक होता है। कोई भी टाइपकास्ट असंगत प्रकारों का उपयोग करते समय संकुचन को बेकार नहीं करेगा, क्योंकि यह हमेशा संकलक को एक त्रुटि फेंकने का कारण होगा।
thePyroEagle

6
यह गोल नहीं है। यह डाली (= छंटनी की गई) है
लुकास ईडर

483

इस कास्टिंग का एक अच्छा उदाहरण * = या / = का उपयोग कर रहा है

byte b = 10;
b *= 5.7;
System.out.println(b); // prints 57

या

byte b = 100;
b /= 2.5;
System.out.println(b); // prints 40

या

char ch = '0';
ch *= 1.1;
System.out.println(ch); // prints '4'

या

char ch = 'A';
ch *= 1.5;
System.out.println(ch); // prints 'a'

11
@ अक्षतर्वाल च एक चेर है। 65 * 1.5 = 97.5 -> समझे?
सजल दत्ता

79
हाँ, लेकिन मैं यहाँ आने वाले कुछ शुरुआती लोगों को देख सकता हूँ, इसे पढ़कर, और यह सोचकर कि आप किसी भी चरित्र को ऊपरी मामले से निचले मामले में 1.5 से गुणा करके परिवर्तित कर सकते हैं।
दाऊद इब्न करीम

103
@DavidWallace जब तक कोई भी चरित्र है A;)
पीटर लॉरी

14
@PeterLawrey & @DavidWallace मैं आपका रहस्य उजागर करूंगा - ch += 32 = D
मिन्हास कमल

256

बहुत अच्छा सवाल है। जावा भाषा विशिष्टता अपने सुझाव पुष्टि करता है।

उदाहरण के लिए, निम्न कोड सही है:

short x = 3;
x += 4.6;

और x में परिणाम 7 का मान है क्योंकि यह इसके बराबर है:

short x = 3;
x = (short)(x + 4.6);

15
या अधिक मजेदार: "int x = 33333333; x + = 1.0f;"।
सुपरकैट

5
@ सुपरकैट, यह क्या प्रवंचना है? एक व्यापक रूपांतरण जो गलत तरीके से गोल किया गया है, इसके बाद एक परिणाम है जो वास्तव में परिणाम नहीं बदलता है, सामान्य मानव दिमागों के लिए सबसे अप्रत्याशित है एक परिणाम का उत्पादन करने के लिए फिर से इंट करने के लिए कास्टिंग।
नेक्सस

1
@ एक्सएक्सयू: आईएमएचओ, रूपांतरण नियमों double->floatको व्यापक रूप से माना जाना चाहिए , इस प्रकार के मान floatवास्तविक संख्याओं की पहचान करते हैं जो विशेष रूप से टाइप के मुकाबले कम हैं double। यदि एक doubleपूर्ण डाक पते के floatरूप में और 5-अंकों वाले पोस्टल कोड के रूप में कोई विचार करता है , तो एक पोस्टल कोड के लिए अनुरोध को पूरा पता देना संभव है, लेकिन केवल एक पोस्टल कोड के लिए दिए गए एक पूर्ण पते के लिए अनुरोध को सटीक रूप से बताना संभव नहीं है। । एक डाक कोड के लिए एक सड़क का पता
बदलना

1
... कोई है जो एक पूरा पता की जरूरत है आम तौर पर सिर्फ एक पोस्टल कोड के लिए पूछ नहीं किया जाएगा। से रूपांतरण float->doubleयूएस पोस्टल कोड 90210 को "यूएस पोस्ट ऑफिस, बेवर्ली हिल्स सीए 90210" के साथ परिवर्तित करने के बराबर है।
सुपरकट

181

हाँ,

मूल रूप से जब हम लिखते हैं

i += l; 

संकलक इसे करने के लिए धर्मान्तरित

i = (int)(i + l);

मैंने अभी .classफाइल कोड चेक किया है ।

वास्तव में एक अच्छी बात है


3
क्या आप बता सकते हैं कि यह कौन सा क्लासफाइल है?
nanofarad

6
@ हेक्सफ़्रेक्शन: आपको क्लास फाइल से क्या मतलब है? अगर आप अपनी पोस्ट में मेरे द्वारा बताई गई क्लास फाइल के बारे में पूछ रहे हैं, तो यह आपके जावा क्लास के कम्पलसिव वर्जन
उमेश अवस्थी

3
ओह, आपने "क्लास" कोड का उल्लेख किया है, जिसके कारण मुझे विश्वास है कि एक विशिष्ट क्लासफाइल शामिल था। मैं समझता हूं कि अब आपका क्या मतलब है।
नानोफारड

@ बोगदान जो ठीक से उपयोग किए गए फोंट के साथ समस्या नहीं होनी चाहिए। एक प्रोग्रामर जो प्रोग्रामिंग के लिए whe गलत फॉन्ट चुनता है, को स्पष्ट रूप से सोचना चाहिए कि कैसे आगे बढ़ना है ...
glglgl

7
@glglgl मैं असहमत हूं कि किसी को उन मामलों में अंतर करने के लिए फ़ॉन्ट पर भरोसा करना चाहिए ... लेकिन हर किसी को यह चुनने की स्वतंत्रता है कि क्या सबसे अच्छा है।
बोगडान अलेक्जेंड्रू

92

आप से डाली की जरूरत longके लिए int explicitlyके मामले में i = i + l तो यह संकलन और सही उत्पादन दे देंगे। पसंद

i = i + (int)l;

या

i = (int)((long)i + l); // this is what happens in case of += , dont need (long) casting since upper casting is done implicitly.

लेकिन इसके मामले में +=यह ठीक काम करता है क्योंकि ऑपरेटर स्पष्ट रूप से टाइपिंग को राइट वेरिएबल के प्रकार से लेफ्ट वेरिएबल के प्रकार से करता है, इसलिए इसे स्पष्ट रूप से नहीं डालना चाहिए।


7
इस मामले में, "निहित कलाकार" हानिप्रद हो सकता है। वास्तव में, जैसा कि @LukasEder अपने उत्तर में कहता है, कलाकारों को intइसके बाद किया जाता है +। संकलक होगा (चाहिए?) एक चेतावनी फेंक अगर यह वास्तव में longकरने के लिए डाली int
रोमेन

63

यहां समस्या में टाइप कास्टिंग शामिल है।

जब आप int और long जोड़ते हैं,

  1. Int ऑब्जेक्ट को लंबे और दोनों में जोड़ा जाता है और आपको लंबी वस्तु मिलती है।
  2. लेकिन लंबी वस्तु को संक्षेप में int के लिए नहीं डाला जा सकता है। तो, आपको यह स्पष्ट रूप से करना होगा।

लेकिन +=इस तरह से कोडित किया जाता है कि यह टाइप कास्टिंग करता है।i=(int)(i+m)


54

जावा प्रकार में रूपांतरण स्वचालित रूप से किए जाते हैं जब असाइनमेंट ऑपरेशन के दाहिने हाथ की तरफ अभिव्यक्ति का प्रकार असाइनमेंट के बाएं हाथ की तरफ चर के प्रकार को सुरक्षित रूप से बढ़ावा दिया जा सकता है। इस प्रकार हम सुरक्षित रूप से असाइन कर सकते हैं:

 बाइट -> शॉर्ट -> इंट -> लॉन्ग -> फ्लोट -> डबल। 

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


2
अरे, लेकिन long2 गुना बड़ा है float
प्रदर्शित नाम

11
A floatहर संभव intमूल्य doubleनहीं पकड़ सकता है , और हर संभव longमूल्य नहीं पकड़ सकता है ।
एलेक्स एमडीसी

2
"सुरक्षित रूप से परिवर्तित" से आपका क्या मतलब है? उत्तर के उत्तरार्द्ध से मैं यह कह सकता हूं कि आपका मतलब था स्वचालित रूपांतरण (निहित कास्ट) जो कि फ्लोट के मामले में निश्चित रूप से सही नहीं है -> लंबा। फ्लोट पी = 3.14 एफ; लंबी बी = पी; कंपाइलर त्रुटि का परिणाम देगा।
ल्यूक

1
पूर्णांक आदिम प्रकारों के साथ आप फ्लोटिंग पॉइंट आदिम प्रकारों को अलग करना बेहतर होगा। वे एक ही बात नहीं कर रहे हैं
thePyroEagle

जावा में सरलीकृत रूपांतरण नियम हैं जिनमें कई पैटर्नों में जातियों के उपयोग की आवश्यकता होती है, जहाँ बिना जातियों के व्यवहार अन्यथा अपेक्षाओं से मेल खाते हैं, लेकिन कई पैटर्नों में जातियों की आवश्यकता नहीं होती है जो आमतौर पर गलत होते हैं। उदाहरण के लिए, एक कंपाइलर double d=33333333+1.0f;बिना किसी शिकायत के स्वीकार कर लेगा , भले ही परिणाम 33333332.0 संभवतः वह नहीं होगा जो इरादा था (संयोगवश, 33333334.0f का अंकगणितीय-सही उत्तर floatया तो प्रतिनिधित्व योग्य होगा int) या ।
सुपरकैट

46

कभी-कभी, एक साक्षात्कार में ऐसा प्रश्न पूछा जा सकता है।

उदाहरण के लिए, जब आप लिखते हैं:

int a = 2;
long b = 3;
a = a + b;

कोई स्वचालित टाइपकास्टिंग नहीं है। C ++ में उपरोक्त कोड को संकलित करने में कोई त्रुटि नहीं होगी, लेकिन जावा में आपको कुछ ऐसा मिलेगा Incompatible type exception

तो इससे बचने के लिए, आपको अपना कोड इस तरह लिखना होगा:

int a = 2;
long b = 3;
a += b;// No compilation error or any exception due to the auto typecasting

6
opजावा में इसके उपयोग के लिए सी ++ में उपयोग की तुलना के बारे में जानकारी के लिए धन्यवाद । मुझे हमेशा त्रिविम के इन बिट्स को देखना पसंद है और मुझे लगता है कि वे बातचीत में कुछ योगदान करते हैं जो अक्सर छोड़ दिया जा सकता है।
थॉमस

2
हालाँकि यह सवाल अपने आप में दिलचस्प है, एक साक्षात्कार में यह पूछना बेवकूफी है। यह साबित नहीं करता है कि व्यक्ति एक अच्छी गुणवत्ता कोड का उत्पादन कर सकता है - यह सिर्फ यह साबित करता है कि उसके पास ओरेकल प्रमाणपत्र परीक्षा की तैयारी के लिए पर्याप्त धैर्य था। और एक खतरनाक ऑटो-रूपांतरण का उपयोग करके असंगत प्रकारों से "बचना" और इस प्रकार संभव अतिप्रवाह त्रुटि को छिपाना, शायद यह भी साबित करता है कि व्यक्ति संभावित रूप से एक अच्छी गुणवत्ता कोड का उत्पादन करने में सक्षम नहीं है। इन सभी ऑटो-रूपांतरणों और ऑटो-बॉक्सिंग और सभी के लिए जावा लेखकों को धिक्कार है!
होन्ज़ा ज़िदेक

25

मुख्य अंतर यह है कि इसके साथ a = a + b, कोई टाइपकास्टिंग नहीं चल रही है, और इसलिए कंपाइलर आपको टाइपकास्टिंग नहीं करने के लिए नाराज हो जाता है। लेकिन इसके साथ a += b, जो वास्तव में कर रहा है वह टाइपकास्टिंग bके साथ संगत है a। इसलिए यदि आप

int a=5;
long b=10;
a+=b;
System.out.println(a);

आप वास्तव में क्या कर रहे हैं:

int a=5;
long b=10;
a=a+(int)b;
System.out.println(a);

5
कंपाउंड असाइनमेंट ऑपरेटर बाइनरी ऑपरेशन के परिणाम का एक संकीर्ण रूपांतरण करते हैं, न कि दाएं हाथ का ऑपरेंड। इसलिए आपके उदाहरण में, 'a + = b' 'a = a + (int) b' के बराबर नहीं है, लेकिन जैसा कि अन्य उत्तरों द्वारा यहाँ 'a = (int) (a + b)' के रूप में समझाया गया है।
लेउ बलोच

13

यहाँ सूक्ष्म बिंदु ...

i+jजब jएक डबल है और iएक इंट है के लिए एक अंतर्निहित टाइपकास्ट है। जब उनके बीच कोई ऑपरेशन होता है, तो Java ALWAYS एक पूर्णांक को एक दोहरे में परिवर्तित करता है।

यह स्पष्ट करने के लिए कि एक पूर्णांक i+=jकहां iहै और jएक डबल है जिसे वर्णित किया जा सकता है

i = <int>(<double>i + j)

देखें: अंतर्निहित कास्टिंग का यह विवरण

आप अपने टाइपकास्ट करना चाह सकते हैं jकरने के लिए (int)स्पष्टता के लिए इस मामले में।


1
मुझे लगता है कि एक और दिलचस्प मामला हो सकता है int someInt = 16777217; float someFloat = 0.0f; someInt += someFloat;। शून्य को जोड़ना someIntइसके मूल्य को प्रभावित नहीं करने के लिए , लेकिन इसके मूल्य में परिवर्तन someIntको बढ़ावा दे floatसकता है।
सुपरकैट

4

जावा भाषा विशिष्टता को परिभाषित करता है E1 op= E2के बराबर होने का E1 = (T) ((E1) op (E2))जहां Tका एक प्रकार है E1और E1एक बार मूल्यांकन किया जाता है

यह एक तकनीकी जवाब है, लेकिन आप सोच रहे होंगे कि ऐसा क्यों है। ठीक है, चलो निम्नलिखित कार्यक्रम पर विचार करें।

public class PlusEquals {
    public static void main(String[] args) {
        byte a = 1;
        byte b = 2;
        a = a + b;
        System.out.println(a);
    }
}

यह प्रोग्राम क्या छापता है?

क्या आपने 3 अनुमान लगाया? बहुत बुरा, यह कार्यक्रम संकलित नहीं करेगा। क्यों? खैर, ऐसा होता है कि जावा में बाइट्स के अलावा वापसी को परिभाषित किया गया हैint । यह, मेरा मानना ​​है कि जावा वर्चुअल मशीन बाइटकोड को बचाने के लिए बाइट संचालन को परिभाषित नहीं करता है (सभी के बाद सीमित संख्या में है), पूर्णांक संचालन का उपयोग करने के बजाय एक भाषा में लागू किया गया कार्यान्वयन विवरण है।

लेकिन अगर a = a + bयह काम नहीं करता है, तो इसका मतलब यह होगा कि a += bबाइट्स के लिए काम नहीं करेगा यदि इसे E1 += E2परिभाषित किया गया था E1 = E1 + E2। जैसा कि पिछले उदाहरण से पता चलता है, वास्तव में ऐसा ही होगा। +=बाइट और शॉर्ट्स के लिए ऑपरेटर का काम करने के लिए एक हैक के रूप में , एक निहित कास्ट शामिल है। यह हैक के लिए बहुत अच्छा नहीं है, लेकिन जावा 1.0 के काम के दौरान, भाषा को शुरू करने के लिए जारी करने पर ध्यान केंद्रित किया गया था। अब, पीछे की संगतता के कारण, जावा 1.0 में पेश किए गए इस हैक को हटाया नहीं जा सका।

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