क्या जावा में "यह" कभी भी अशक्त हो सकता है?


109

इस लाइन को एक क्लास विधि में देखा और मेरी पहली प्रतिक्रिया डेवलपर को उपहास करने के लिए थी जिसने इसे लिखा था .. लेकिन फिर, मुझे लगा कि मुझे यह सुनिश्चित करना चाहिए कि मैं पहले सही था।

public void dataViewActivated(DataViewEvent e) {
    if (this != null)
        // Do some work
}

क्या वह रेखा कभी असत्य का मूल्यांकन करेगी?


104
हमेशा पहले उपहास करो और बाद में सवाल करो। माफी माँगने की तुलना में आसान है कि किसी व्यक्ति को किसी भी तरह के ब्रिमस्टोन में आंसू बहाने का सुनहरा मौका दें।
जोएल इथरटन

5
"ब्रिमस्टोन की हड़बड़ाहट" शब्द के लिए +1।
मार्टी पिट

13
तुम्हें पता है कि क्या अजीब है? यह एक कंपाइलर बग के कारण C # में हो सकता है!
ब्लाइंडी

1
@ Bindy कोड नमूने के लिए +1 देगा।
नाथन फेगर

6
कु # में यह अशक्त हो सकता है। कुछ किनारे मामलों में। मेरे पास एक ही आवेग था: चूसने वाले का उपहास करना लेकिन फिर मैं शांत हो गया। एक नज़र यहाँ है: stackoverflow.com/questions/2464097/…
आंद्रेई रोंएना

जवाबों:


88

नहीं, यह नहीं हो सकता। यदि आप उपयोग कर रहे हैं this, तो आप उदाहरण में हैं इसलिए thisअशक्त नहीं है।

जेएलएस कहता है:

प्राथमिक अभिव्यक्ति के रूप में उपयोग किए जाने पर, यह कीवर्ड उस मान को दर्शाता है जो उस ऑब्जेक्ट का संदर्भ है जिसके लिए इंस्टेंस विधि (oked15.12), या निर्माण की जा रही ऑब्जेक्ट को लागू किया गया था।

यदि आपने किसी ऑब्जेक्ट को विधि से लागू किया है, तो वह वस्तु मौजूद है या आपके पास NullPointerExceptionपहले (या यह एक स्थिर विधि है लेकिन फिर, आप इसमें उपयोग नहीं कर सकते हैं this)।


संसाधन:


4
मैं जावा के बारे में गहराई से नहीं जानता, लेकिन C ++ thisमें एक इंस्टेंस विधि NULL हो सकती है। इसलिए मैं काफी आश्वस्त नहीं हूं कि जावा में यह पर्याप्त कारण है।
kennytm

4
कुछ की तरह शून्य सूचक अपवाद को foo.bar()फेंक दिया जाएगा जब fooखोज की जाएगी null। यह विधि में प्रवेश करने से पहले होता है, लेकिन वास्तविक कहानी यह है कि कॉल करने का प्रयास करने की कोई विधि नहीं है।
क्लॉडिउ

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

5
@ केनी: अपरिभाषित व्यवहार के बिना नहीं , हालांकि यदि आप अपने कार्यान्वयन के विवरण जानते हैं, तो आप इसका उपयोग कर सकते हैं।

4
मैं इस निश्चित उत्तर की सदस्यता नहीं लूंगा, भले ही यह पूर्ण समझ में आता हो। मेरे पास एक एंड्रॉइड ऐप के लिए क्रैश रिपोर्ट है, जहां यह == अशक्त है, जब चर के बाद एक आवृत्ति विधि को सही कहा जाता है, किसी अन्य थ्रेड से शून्य-ified किया जा रहा है। वास्तविक कॉल तब भी होता है जब चर शून्य होता है, और यह तब दुर्घटनाग्रस्त हो जाता है जब यह एक उदाहरण सदस्य को पढ़ने की कोशिश करता है :)
एड्रियन क्रेउ सिप

63

यह अपने आप से पूछने जैसा है "क्या मैं जीवित हूं?" thisकभी अशक्त नहीं हो सकता


44
क्या मैं ज़िंदा हूँ ?! हे भगवान मैं अब और नहीं जानता कि
Claudiu

आप इसे this != nullस्पष्ट कर रहे हैं जैसे कि यह स्पष्ट था। यह नहीं है - C ++ में, उदाहरण के लिए, एक गैर-आभासी विधि के लिए thisअच्छी तरह से हो सकता है NULL
निकी

1
@ मिनी कुछ अर्थों में, यह स्वयं स्पष्ट है। C ++ में भी, ऐसा होने वाले किसी भी कार्यक्रम में अपरिभाषित व्यवहार होता है। यह GCC पर वर्चुअल फ़ंक्शंस के लिए भी हो सकता है: ideone.com/W7RmU
जोहान्स शहाब -

8
@ जॉन: आप कर रहे हैं। यातना का एक हिस्सा यह है कि आप इसकी पुष्टि नहीं कर सकते।

@ जोहान्सचैब-लिट यह सच नहीं है कि इसके लिए अशक्त रेफरी के साथ c ++ प्रोग्राम का व्यवहार अपरिभाषित है। इसे तब तक परिभाषित किया जाता है जब तक आप इस पर विचार नहीं करते हैं
Rune FS

9

नहीं , कभी भी यह 'कीवर्ड' उस वर्ग के दायरे के भीतर उस वर्ग के वर्तमान जीवंत उदाहरण (वस्तु) का प्रतिनिधित्व नहीं करता है, जिसके साथ आप इसके सभी क्षेत्रों और सदस्यों (निर्माणकर्ताओं सहित) और इसके मूल वर्ग के दृश्यमान लोगों तक पहुंच सकते हैं।

और, और अधिक दिलचस्प, इसे स्थापित करने का प्रयास करें:

this = null;

इसके बारे में सोचो? यह कैसे संभव हो सकता है, यह उस शाखा को काटने जैसा नहीं होगा जिस पर आप बैठे हैं। चूंकि कीवर्ड 'यह' वर्ग के दायरे में उपलब्ध है, इसलिए जैसे ही आप यह कहते हैं = अशक्त; कक्षा के भीतर कहीं भी आप मूल रूप से JVM को कुछ ऑपरेशन के बीच में उस ऑब्जेक्ट को सौंपी गई मेमोरी को मुफ्त करने के लिए कह रहे हैं, जो JVM को होने की अनुमति नहीं दे सकता है क्योंकि उस ऑपरेशन को खत्म करने के बाद उसे सुरक्षित रूप से वापस लौटने की आवश्यकता होती है।

इसके अलावा, प्रयास करने this = null;से कंपाइलर त्रुटि होगी। कारण बहुत सरल है, जावा (या किसी भी भाषा) में एक कीवर्ड को कभी भी मान नहीं दिया जा सकता है यानी एक कीवर्ड कभी भी असाइनमेंट ऑपरेशन के बाएं मूल्य नहीं हो सकता है।

अन्य उदाहरण, आप नहीं कह सकते:

true = new Boolean(true);
true = false;

अच्छी व्याख्या मित्र।
पंकज शर्मा

@PankajSharma धन्यवाद :)
sactiw

मुझे यह मिला क्योंकि मैं देखना चाहता था कि क्या मैं उपयोग कर सकता हूं this = null। मेरा उदाहरण एंड्रॉइड में था जहां मैं एक दृश्य को हटाना चाहता था और ऑब्जेक्ट को अशक्त करने के लिए हैंडल को सेट करना चाहता था। तब मैं एक ऐसी विधि का उपयोग करना चाहता था remove()जो वास्तविक दृश्य को हटा दे और फिर हैंडलर-ऑब्जेक्ट को बेकार कर दिया जाएगा, इसलिए मैं इसे शून्य करना चाहता था।
योकि

यकीन नहीं होता कि मैं आपके दावों से सहमत हूं। (कम से कम मध्य भाग; लैवल्यू भाग ठीक है ... हालांकि मुझे पूरा यकीन है कि वास्तव में टूटी हुई भाषाएं हैं जो आपको उदाहरण के लिए सही या गलत असाइन करने की अनुमति देती हैं (और यहां तक ​​कि जिन भाषाओं को मैं टूटी हुई नहीं कहूंगा) परावर्तन या समान प्रवंचना))। वैसे भी, अगर मेरे पास कुछ ऑब्जेक्ट फू है और मैं यह करने के लिए (अनदेखी कर रहा था कि यह अवैध है) foo.this = null, फू अभी भी मेमोरी को इंगित करेगा और इसलिए JVM कचरा इकट्ठा नहीं करेगा।
टेलीफोन

@ अच्छी तरह से सवाल ठीक जावा भाषा के बारे में बात करता है, इसके अलावा, मैं किसी भी भाषा में नहीं आया हूं जहां इस = शून्य की अनुमति है। यही है, अगर ऐसी भाषाएं मौजूद हैं, तो मुझे बहुत संदेह है कि ऐसी भाषाओं में 'यह' एक ही संदर्भ और विचारधारा होगी।
sactiw

7

यदि आप के साथ -target 1.3या पहले संकलित करते हैं , तो एक बाहरी this हो सकता हैnull । या कम से कम यह करने के लिए इस्तेमाल किया ...


2
मुझे लगता है कि प्रतिबिंब के माध्यम से हम बाहरी को शून्य करने के लिए सेट कर सकते हैं। किसी के प्रति अप्रैल मूर्ख मजाक हो सकता है जब उसे संदर्भित करने में अशक्त सूचक अपवाद मिलाOuter.this.member
21

3

सं। किसी वर्ग के उदाहरण की एक विधि को कॉल करने के लिए, उदाहरण मौजूद है। उदाहरण के रूप में संदर्भित विधि के लिए एक पैरामीटर के रूप में निहित है this। अगर thisथा, nullतो कोई तरीका नहीं था कि किस तरीके की कॉल की जाए।


3

यह पर्याप्त नहीं है कि भाषा इसे लागू करे। VM को इसे लागू करने की आवश्यकता है। जब तक वीएम इसे लागू नहीं करता है आप एक कंपाइलर लिख सकते हैं जो जावा में लिखी विधि को कॉल करने से पहले अशक्त जांच को लागू नहीं करता है। उदाहरण विधि आह्वान के लिए opcodes में स्टैक देखने के लिए इस रेफ को लोड करना शामिल है: http://java.sun.com/docs/books/jvms/second_edition/html/Compiling.doc.html#14787 । एक शून्य रेफ के लिए इसे प्रतिस्थापित करने से वास्तव में परीक्षण गलत होगा


3

स्थिर वर्ग के तरीकों में, thisतब से परिभाषित नहीं किया जाता है जब तक thisकि उदाहरणों के साथ जुड़ा हुआ है और कक्षाएं नहीं हैं। मेरा मानना ​​है कि यह thisस्थिर संदर्भ में कीवर्ड का उपयोग करने का प्रयास करने के लिए एक संकलक त्रुटि देगा ।


2

एक सामान्य thisकभी भी nullवास्तविक जावा कोड 1 में नहीं हो सकता है , और आपका उदाहरण एक सामान्य का उपयोग करता है this। अधिक जानकारी के लिए अन्य उत्तर देखें।

एक योग्य this चाहिए कभी नहीं हो null, लेकिन इस तोड़ने के लिए संभव है। निम्नलिखित को धयान मे रखते हुए:

public class Outer {
   public Outer() {}

   public class Inner {
       public Inner() {}

       public String toString() {
           return "outer is " + Outer.this;  // Qualified this!!
       }
   }
}

जब हम एक उदाहरण बनाना चाहते हैं Inner, तो हमें यह करने की आवश्यकता है:

public static void main(String[] args) {
    Outer outer = new Outer();
    Inner inner = outer.new Inner();
    System.out.println(inner);

    outer = null;
    inner = outer.new Inner();  // FAIL ... throws an NPE
}

आउटपुट है:

outer is Outer@2a139a55
Exception in thread "main" java.lang.NullPointerException
        at Outer.main(Outer.java:19)

यह दर्शाता है कि इसके संदर्भ के Innerसाथ बनाने का हमारा प्रयास विफल रहा है।nullOuter

वास्तव में, यदि आप "शुद्ध जावा" लिफाफे के भीतर रहते हैं, तो आप इसे नहीं तोड़ सकते।

हालांकि, प्रत्येक Innerउदाहरण में एक छिपा हुआ finalसिंथेटिक क्षेत्र (कहा जाता है "this$0") जिसमें संदर्भ का संदर्भ होता है Outer। यदि आप वास्तव में मुश्किल हैं, तो nullक्षेत्र में असाइन करने के लिए "गैर-शुद्ध" साधनों का उपयोग करना संभव है ।

  • आप Unsafeइसे करने के लिए उपयोग कर सकते हैं ।
  • आप इसे करने के लिए मूल कोड (जैसे JNI) का उपयोग कर सकते हैं।
  • आप इसे प्रतिबिंब का उपयोग करके कर सकते हैं।

किसी भी तरह से आप इसे करते हैं, अंतिम परिणाम यह है कि Outer.thisअभिव्यक्ति null2 का मूल्यांकन करेगी ।

संक्षेप में, एक योग्य होना संभवthis है null। लेकिन यह असंभव है यदि आपका कार्यक्रम "शुद्ध जावा" नियमों का पालन करता है।


1 - मैं हाथ से बाईटकोड को "लिखने" और असली जावा के रूप में उन्हें पास करने के लिए ट्रिक को छूट देता हूं, बीसीईएल या इसी तरह का उपयोग करके बायटेकोड्स को ट्वीक कर रहा हूं, या सहेजे गए रजिस्टरों के साथ देशी कोड और डूडलिंग में जा रहा हूं। IMO, यह जावा नहीं है। हाइपोथेटिक रूप से, इस तरह की चीजें जेवीएम बग के परिणामस्वरूप भी हो सकती हैं ... लेकिन मुझे बग रिपोर्ट देखकर हर याद नहीं है।

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


1

जब आप nullसंदर्भ पर एक विधि लागू करते हैं , तो NullPointerExceptionजावा वीएम से फेंक दिया जाएगा। यह विनिर्देशन के अनुसार है, यदि आपका जावा वीएम विनिर्देश का कड़ाई से पालन करता है, thisतो कभी नहीं होगा null


1

यदि विधि स्थिर है, तो कोई भी नहीं है this। यदि विधि आभासी है, तो thisशून्य नहीं हो सकता है, क्योंकि विधि को कॉल करने के लिए, रन-टाइम को thisपॉइंटर का उपयोग करके विटेबल का संदर्भ देना होगा । यदि विधि आभासी नहीं है तो, हाँ, यह संभव हैthis अशक्त है।

C # और C ++ गैर-आभासी तरीकों की अनुमति देते हैं, लेकिन जावा में सभी गैर-स्थिर तरीके आभासी हैं, इसलिए thisकभी भी अशक्त नहीं होंगे।


0

tl; dr; "इस" को केवल एक गैर-स्थैतिक विधि से बुलाया जा सकता है और हम सभी जानते हैं कि एक गैर-स्थिर विधि को किसी प्रकार की वस्तु से बुलाया जाता है, जो शून्य नहीं हो सकती।

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