paint-brush
ब्रेकप्वाइंट: द मैसिव पावर उन्होंने समझाया हैद्वारा@shai.almog

ब्रेकप्वाइंट: द मैसिव पावर उन्होंने समझाया है

द्वारा Shai Almog10m2023/01/02
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

ट्रेसपॉइंट्स (एकेए लॉगपॉइंट्स) के बारे में जानें कि कैसे अपवाद ब्रेकपॉइंट्स को चूसना नहीं पड़ता है, वॉचपॉइंट्स, फ़िल्टर और विधि ब्रेकपॉइंट्स समस्याग्रस्त क्यों हैं।
featured image - ब्रेकप्वाइंट: द मैसिव पावर उन्होंने समझाया है
Shai Almog HackerNoon profile picture

यह एक बड़ा सप्ताह रहा है। मैं वर्तमान में अपनी आगामी डिबगिंग पुस्तक के अंतिम मसौदे की समीक्षा कर रहा हूं। यह हमेशा एक साहसी और रोमांचक क्षण होता है। एक ऐसा क्षण जिसमें अचानक सारे महीने का काम "वास्तविक" हो जाता है।


मैंने youtube के लिए 9 वीडियो भी रिकॉर्ड किए और कुल वीडियो को 29 तक लाया (कई और आने वाले हैं)। मैं दो अतिरिक्त मुफ्त पाठ्यक्रम शुरू कर रहा हूं, एक बिल्कुल शुरुआती लोगों पर लक्षित है


दूसरा आधुनिक जावा प्रोग्रामिंग के बारे में है जिसे मैं वास्तव में जल्द ही लॉन्च करूंगा। दोनों पर मुफ्त होंगे (अनिवार्य "लाइक, सब्सक्राइब और शेयर")।


इस सप्ताह की पोस्ट में, हम ब्रेकप्वाइंट के बारे में बात करेंगे। यह एक लंबा है क्योंकि जब हम ब्रेकपॉइंट कहते हैं तो हमारा मतलब वास्तव में "लाइन-ब्रेकपॉइंट" होता है। उनमें और भी बहुत कुछ है जैसा कि आप नीचे देख सकते हैं।

प्रतिलिपि

स्केल पर डिबगिंग के चौथे भाग में आपका स्वागत है जहां हम गधे को मारते हैं और नाम लेते हैं। परिवर्तनीय नाम!


इस खंड में, हम ब्रेकप्वाइंट पर चर्चा करते हैं जो डिबगिंग के समय काम की सबसे बुनियादी इकाइयाँ हैं। लेकिन उनके पास तोड़ने के अलावा और भी बहुत कुछ है।


हमने अपनी पहली किश्त में सबसे बुनियादी ब्रेकप्वाइंट के बारे में बात की थी। इस बार, हम थोड़ी गहराई में और कुछ कम ज्ञात बारीकियों पर ध्यान देंगे।

सशर्त विराम बिंदु

हम सशर्त ब्रेकप्वाइंट से शुरू करते हैं। कंडीशनल ब्रेकप्वाइंट हमें ब्रेकप्वाइंट हिट के लिए एक शर्त परिभाषित करते हैं। यह थ्रेड को ब्रेकप्वाइंट पर लगातार रुकने से रोकता है। मैंने इससे पहले पिछले वीडियो में बनाए गए MyThread Marker ऑब्जेक्ट के साथ इस पर चर्चा की थी।


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

विधि विराम बिंदु

विधि विराम बिंदु काफी समस्याग्रस्त हैं।


एक पुनश्चर्या के रूप में, हम विधि में किसी भी रेखा पर एक पंक्ति विराम बिंदु रख सकते हैं, और विराम बिंदु वहीं रुक जाएगा। यह इतना सर्वव्यापी है कि हम इसे "ब्रेकप्वाइंट" कहते हैं।


हम नियंत्रण-F8 के साथ या Command-F8 वाले मैक पर वैकल्पिक रूप से मानक लाइन ब्रेकपॉइंट को टॉगल कर सकते हैं।


जब हम कोई विधि दर्ज करते हैं तो विधि विराम बिंदु रुक जाते हैं। आप सोच सकते हैं कि यह बेकार है। लाइन ब्रेकपॉइंट का उपयोग क्यों नहीं करें?


आप सही होंगे। मेथड ब्रेकप्वाइंट बहुत धीमे हैं, और आपको उनका उपयोग नहीं करना चाहिए: इसके लिए... हालांकि मेथड ब्रेकप्वाइंट के लिए एक उपयोग मामला है।


ध्यान दें कि क्योंकि विधि ब्रेकप्वाइंट इतने धीमे हैं, वे आमतौर पर आईडीई द्वारा अनुकरण किए जाते हैं। यह विधि ब्रेकपॉइंट अनुकरण करने के लिए लाइन ब्रेकपॉइंट्स का उपयोग करता है। यह आईडीई के उपयोगकर्ताओं के रूप में हमारे लिए ज्यादातर सहज है, लेकिन हमें इसके बारे में जानने की जरूरत है क्योंकि अतीत में ऐसा नहीं था।


आप अभी भी स्टैक ओवरफ्लो पर उपयोगकर्ताओं से विधि ब्रेकपॉइंट्स की धीमी गति के बारे में शिकायत करने वाले संदेश पा सकते हैं।


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


पैटर्न के आधार पर ऐसी सभी विधियों पर रोक लगाने के लिए हम इस तरह की अभिव्यक्ति का उपयोग करके ऐसा कर सकते हैं। यह दूर की कौड़ी लग सकता है लेकिन वास्तव में बहुत उपयोगी है यदि आपके पास एक सार आधार वर्ग है जिसके उपवर्ग एक नामकरण परंपरा का पालन करते हैं और उनके पास कई संबंधित तरीके हैं।


आप सब कुछ ट्रैक करना चाहते हैं, और आप इस दृष्टिकोण का उपयोग करके ऐसा कर सकते हैं। ध्यान दें कि आप यहां ट्रेसपॉइंट्स का भी उपयोग कर सकते हैं और बहुत गहरी लॉगिंग प्राप्त कर सकते हैं। हम कुछ मिनटों में ट्रेसपॉइंट्स पर चर्चा करेंगे।

फील्ड वॉचपॉइंट्स

फील्ड वॉचप्वाइंट आपका विशिष्ट ब्रेकप्वाइंट नहीं है। हर बार जब फ़ील्ड का मान बदलता है या हर बार इसे पढ़ा जाता है, तो वॉचपॉइंट बंद हो जाएगा। यह एक ऐसे मामले को पकड़ने का एक शानदार तरीका है जहां कुछ कोड एक चर को बदलते हैं या यह पता लगाते हैं कि फ़ील्ड मान कोड में कैसे फैलता है।


ध्यान दें कि हम ट्यून कर सकते हैं कि क्या यह रीड ऑपरेशंस पर रुकता है, ऑपरेशंस लिखता है, या दोनों इस डायलॉग का उपयोग करता है। हम वॉचपॉइंट को सशर्त भी बना सकते हैं जैसे हम किसी अन्य ब्रेकपॉइंट के साथ कर सकते हैं।


इसे वॉचपॉइंट कहा जाता है न कि ब्रेकपॉइंट क्योंकि यह वह बिंदु नहीं है जहां कोड रुकता है। यह पहुँच के बिंदु पर रुकता है, मैदान पर ही नहीं।

विराम बिंदु प्रबंधन

आईडीई सभी ब्रेकप्वाइंट के लिए एक प्रबंधन यूआई प्रदान करते हैं। हम पहले से मौजूद ब्रेकपॉइंट्स को प्रबंधित कर सकते हैं और व्यू ब्रेकपॉइंट्स मेनू में नए ब्रेकपॉइंट्स बना सकते हैं। मैं इसे ब्रेकप्वाइंट मेनू विकल्प के माध्यम से खोल सकता हूं, या मैं Shift-Control-F8 कुंजी संयोजन का उपयोग कर सकता हूं।


ध्यान दें कि, एक मैक पर, हमें नियंत्रण कुंजी के बजाय कमांड का उपयोग करने की आवश्यकता होती है।


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

अपवाद ब्रेकप्वाइंट चूसते हैं (या वे करते हैं?)

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


लेकिन मैं कई मामलों के बारे में नहीं सोच सकता जहां यह हुआ, और मुझे पहले से ही उस रेखा को नहीं पता था जहां अपवाद फेंक दिया गया था।


अधिक मूल्यवान उपयोग मामला सभी अपवादों को पकड़ रहा है। यह उपयोगी होने का कारण यह है कि मैं कभी-कभी डीबगिंग करते समय कंसोल को नहीं देख सकता। अपवाद वहां लॉग हो सकते हैं और मैं उन्हें पूरी तरह याद कर सकता हूं।


मैं डिबग सत्र को पुनः आरंभ कर सकता हूं और इन अपवादों को याद कर सकता हूं। लेकिन अगर एक ब्रेकप्वाइंट अचानक एक अपवाद पर रुक जाता है, तो यह चूकना मुश्किल है। समस्या यह है कि सभी अपवादों को पकड़ना डिफ़ॉल्ट रूप से टूटा हुआ है!


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


कैच को सक्षम करने के बाद, मैं जारी रखने की कोशिश करता हूं, लेकिन यह बार-बार बार-बार ब्रेकपॉइंट हिट करता है। कोड पृष्ठभूमि में एक वेब सेवा का चुनाव करता है। उस वेब सेवा में एक HTTP शीर्षलेख गुम है, इसलिए उस शीर्षलेख को पार्स करने वाला कोड NumberFormatException पर विफल रहता है।


हम उस कोड पर अटके हुए हैं जो उस अपवाद को फेंकता है जो मान्य है क्योंकि जावा ने उस कोड को लिखे जाने पर संख्यात्मक हेडर को पार्स करने का दूसरा तरीका प्रदान नहीं किया था।


तो हम क्या कर सकते हैं? यह प्रभावी रूप से लगभग किसी भी वास्तविक दुनिया के आवेदन के लिए किसी भी अपवाद को बेकार कर देता है।


आइए विंडो को थोड़ा सा खिसकाएं और फिर यह देखने के लिए ज़ूम इन करें कि हम यहां क्या कर रहे हैं।


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


एक बार जब मैं ओके दबाता हूं, तो मैं जारी रख सकता हूं, और एप्लिकेशन समस्याग्रस्त अपवादों को तोड़े बिना चलता है। अन्य अपवाद हमेशा की तरह काम करेंगे और हमारे कोड में कुछ टूटने पर हमें बताएंगे!


यह आश्चर्यजनक है कि यह IDE डिफ़ॉल्ट नहीं है। इसके बिना, सुविधा व्यावहारिक रूप से बेकार है।

ट्रेसपॉइंट्स (उर्फ लॉगपॉइंट्स)

ट्रेसप्वाइंट या लॉगप्वाइंट हमारे पास सबसे महत्वपूर्ण प्रकार के ब्रेकप्वाइंट हैं। हम गटर पर शिफ्ट-क्लिक करके ट्रेसपॉइंट जोड़ सकते हैं। यह एक परिचित ब्रेकप्वाइंट संवाद खोलता है, लेकिन यह थोड़ा अलग दिखता है। सबसे पहले इस पर ध्यान दें:


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


ट्रेसपॉइंट वर्तमान थ्रेड को निलंबित नहीं करता है। एप्लिकेशन ब्रेकपॉइंट हिट करता है और फिर बिना रुके चलता रहता है। यह बहुत ही शानदार है, आप कैसे आगे बढ़ते हैं?


ठीक है, तुम नहीं। इसके बजाय, हम और भी कई काम कर सकते हैं...


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


किसी सूची में बहुत सारे निशान पढ़ना और उसका अनुसरण करना कठिन है। मैं जिस चीज पर ध्यान देना चाहता हूं वह कुछ और है।


ध्यान दें कि मूल्यांकन और लॉग में पहले से ही cnt मान था क्योंकि मेरे पास गटर में शिफ्ट-क्लिक करने से पहले IDE में cnt मान चुना गया था।


हम यहां कोई भी अभिव्यक्ति लिख सकते हैं जिसे हम प्रिंट करना चाहते हैं। मैं वर्णनात्मक तार आदि लिखने के लिए एक विधि का आह्वान कर सकता हूं। यह वस्तुतः एक मानक लॉग स्टेटमेंट है जिसे मैं कोड में गतिशील रूप से जोड़ सकता हूं। ध्यान दें कि मैं अभी भी इस ट्रेसपॉइंट को किसी सशर्त ब्रेकपॉइंट की तरह सशर्त बना सकता हूं।


इसका मतलब है कि मैं इस समय किसी भी मूल्य को प्रिंट कर सकता हूं। बिल्कुल किसी लकड़हारे की तरह। यह एक शानदार फीचर है। इन ट्रेसपॉइंट्स के साथ हमने पहले चर्चा की गई विधि विराम बिंदुओं की कल्पना करें; हम तुरंत पैमाने पर लॉग इन कर सकते हैं। चलिए OK दबाते हैं।


और फिर इस प्रोग्राम को रन करें; हम कंसोल पर मुद्रित ट्रेसपॉइंट में जोड़े गए लॉग को देख सकते हैं जैसे कि हमने इसे कोड में लिखा था!

समूहीकरण और नामकरण

एक बार जब हम अपने डिबगिंग को बढ़ा देते हैं तो ग्रुपिंग और नामकरण महत्वपूर्ण होते हैं।


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


लेकिन अच्छी बात यह है कि हम ब्रेकप्वाइंट के लिए कस्टम समूह बना सकते हैं और समूह में ब्रेकप्वाइंट को एक टॉगल से अक्षम कर सकते हैं। यह बहुत सुविधाजनक है!'


यह हमें एक स्थिति तक पहुँचने की कोशिश करते समय जारी रखने के लिए थकाऊ दबाव से बचाता है और हमें कई ब्रेकप्वाइंट प्रबंधित करने देता है।


लेकिन यहाँ सही मूल्य पैमाने पर है। मान लें कि आपके पास एक जटिल डिबगिंग सत्र है जिसमें एकाधिक ट्रेसपॉइंट एक साथ चल रहे हैं।


आप सत्र को समूहीकृत कर सकते हैं और कुछ और डिबग करने के लिए किसी भिन्न शाखा में स्विच करते समय ब्रेकप्वाइंट को अक्षम कर सकते हैं। फिर वापस वहीं जाएं जहां आप काम पूरा करने के बाद थे।

ब्रेकप्वाइंट अक्षम करें

कभी-कभी एक ब्रेकप्वाइंट लगातार हिट होता है, और हमें केवल एक विशिष्ट स्टैक की आवश्यकता होती है।


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


यह अपवादों और अपवाद ब्रेकप्वाइंट के साथ भी काम करता है, और हम बाद के व्यवहार पर निर्णय ले सकते हैं। क्या हम इसे फिर से निष्क्रिय करना चाहते हैं या हमेशा की तरह जारी रखना चाहते हैं?


यह विफलता के मामले में बहुत उपयोगी है जो केवल एक विशिष्ट मार्ग से गुजरती है। मैं पहली विधि में एक ट्रेसपॉइंट जोड़ सकता हूं। फिर उस ट्रेसपॉइंट में मैं जो वास्तविक ब्रेकपॉइंट चाहता हूं उसे अक्षम करें।

उदाहरण फ़िल्टर

इंस्टेंस फ़िल्टर हमें किसी विशिष्ट ऑब्जेक्ट इंस्टेंस से केवल ब्रेकपॉइंट स्वीकार करने देते हैं।

घड़ी में "इस" के रूप में चिह्नित वर्तमान वस्तु के उदाहरण पर ध्यान दें। ध्यान दें कि इसमें at प्रतीक है जिसके बाद संख्या 656 है।


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


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


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


इस बिंदु पर, हम देख सकते हैं कि इंस्टेंस फ़िल्टर अभी भी ब्रेकप्वाइंट पर रुक रहा है, जिसकी उम्मीद है ...

तो अगला कदम इंस्टेंस फ़िल्टर को एक अलग ऑब्जेक्ट इंस्टेंस में बदलना है। मैं एक संख्या बना रहा हूँ क्योंकि यह सिर्फ एक परीक्षण के लिए है।


ध्यान दें कि जब मैं ब्रेकप्वाइंट पर राइट-क्लिक करता हूं, तो मुझे इस संवाद का एक अनुकूलित संस्करण मिलता है क्योंकि हमारे पास एक इंस्टेंस फ़िल्टर होता है। यह वास्तव में एक साफ-सुथरी विशेषता है जो UI को काम करने में बहुत आसान बनाती है।


अब जबकि हमने वह परिवर्तन कर दिया है, ब्रेकप्वाइंट अब टूटता नहीं है।

कक्षा फ़िल्टर

एक विशिष्ट लाइन ब्रेकप्वाइंट के लिए क्लास फिल्टर का कोई मतलब नहीं है। फ़ील्ड वॉचपॉइंट या अपवाद ब्रेकपॉइंट का उपयोग करते समय क्लास फ़िल्टर समझ में आता है।


इस मामले में, मेरे पास एक सार्वजनिक क्षेत्र है। मैं मुख्य मुख्य वर्ग से सभी पहुंच को अनदेखा करने के लिए फ़ील्ड तक पहुंच फ़िल्टर करता हूं। यदि कोई भिन्न वर्ग फ़ील्ड तक पहुँचता है, तो ब्रेकप्वाइंट हिट हो जाएगा।


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

कॉलर फ़िल्टर

कॉलर फ़िल्टर इनवोकिंग विधि के हस्ताक्षर के आधार पर एक फ़िल्टर लागू करता है। इसे इस्तेमाल करने के लिए हमें फिर से एडवांस्ड मेन्यू में जाना होगा। यह वाइल्डकार्ड का समर्थन करता है इसलिए मैं कॉलर को केवल रन विधि की अनुमति देने के लिए सीमित कर सकता हूं।


ध्यान दें कि यह विधि हस्ताक्षर के लिए JVM संकेतन का उपयोग करता है जो एक बहुत ही जटिल विषय है जिस पर मैं बाद में चर्चा करूंगा। मेरे पास मेरी डीबगिंग पुस्तक में एक अनुभाग है।


विधि अपेक्षा के अनुसार ब्रेकप्वाइंट पर रुकती रहती है क्योंकि, जैसा कि हम यहां देख सकते हैं, रन विधि वास्तव में स्टैक ट्रेस में है। तो, फ़िल्टर ठीक से लागू होता है और ब्रेकपॉइंट हिट करता है।


हम फ़िल्टर के लिए त्वरित संपादन UI में ब्रेकप्वाइंट को फिर से अनुकूलित कर सकते हैं। इस मामले में, मैंने स्टॉप नामक एक विधि खोजने के लिए फ़िल्टर को बदल दिया जो मौजूद नहीं है, और वास्तव में, ब्रेकपॉइंट अब टूटता नहीं है।

अंतिम शब्द

यह एक लंबा वीडियो रहा है, मुझे आशा है कि आपको यह शैक्षिक और व्यापक लगा होगा। अगले वीडियो में, हम डिबगिंग स्ट्रीम और संग्रह के बारे में बात करेंगे।


यदि आपके कोई प्रश्न हैं, तो कृपया टिप्पणी अनुभाग का उपयोग करें। शुक्रिया!