"हाय, अमीगो। आज बिलाबो आपको रिकर्सन के बारे में बताएगा।"

रिकर्सन - 1

जैसा कि आप जानते हैं, जावा में कुछ विधियाँ अन्य विधियों को कॉल करती हैं। इसके अतिरिक्त, जब किसी विधि को कहा जाता है, तो उसके लिए विशिष्ट तर्क पारित किए जाते हैं, लेकिन विधि के स्थानीय चर चलने के दौरान कुछ मान लेते हैं।

"अहां।"

"और जैसा कि आप जानते हैं, विभिन्न विधियों के आंतरिक चर एक दूसरे से स्वतंत्र होते हैं।"

"अहां।"

"तो उस स्थिति की कल्पना करें जहां एक विधि खुद को बुलाती है। इसे रिकर्सन कहा जाता है। उदाहरण के लिए:"

उदाहरण
public static void main(String[] args)
{
 countDown(10);
}

public static void countDown(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  countDown(x - 1);
 }
}
स्क्रीन आउटपुट:
10
9
8
7
6
5
4
3
2
1
Boom!

"मैं देख सकता हूं कि विधि कोड में खुद को कॉल करती है, लेकिन मैं ईमानदारी से समझ नहीं पा रहा हूं कि क्या हो रहा है।"

"ठीक है, उसी के बारे में जो तब होता है जब एक अलग विधि को बुलाया जाता है।"

"नहीं, मैं पूछ रहा हूं कि वेरिएबल्स के साथ क्या होता है? उनके मूल्यों के साथ? और हम विधि से कैसे बाहर निकल सकते हैं? या क्या हम एक ही बार में सब कुछ से बाहर निकल जाते हैं?"

"भगवान की मेहरबानी। यह सब बहुत आसान है। कल्पना कीजिए कि खुद को कॉल करने वाली विधि को कई बार गुणा किया गया है। तब हमारे पास समान स्थिति होगी:"

पुनरावर्ती विधि कॉल वास्तव में क्या होता है
public static void main(String[] args)
{
 countDown(10);
}

public static void countDown(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  countDown(x - 1);
 }
}
public static void main(String[] args)
{
 countDown1(10);
}

public static void countDown1(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  countDown2(x - 1);
 }
}
public static void countDown2(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  countDown3(x - 1);
 }
}
public static void countDown3(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  countDown4(x - 1);
 }
}

public static void countDown4(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  countDown5(x - 1);
 }
}
स्क्रीन आउटपुट: स्क्रीन आउटपुट:
3
2
1
Boom!
3
2
1
Boom!

"दूसरे शब्दों में, प्रत्येक बार एक विधि को बुलाया जाता है (यहां तक ​​​​कि स्वयं भी), नए चर बनाए जाते हैं जो इस विधि के लिए डेटा संग्रहीत करते हैं। कोई साझा चर नहीं हैं।"

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

"मैं समझ गया। और इस तरह के तरीकों से बाहर निकलना कैसे काम करता है? शायद एक उदाहरण?"

"ठीक है। एक उदाहरण एक हजार शब्दों के बराबर है। "यह रहा आपका उदाहरण:"

पुनरावर्ती विधि कॉल पुनरावर्ती विधि कॉल
public static void main(String[] args)
{
 print(3);
}

public static void print(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  print(x - 1);
  System.out.println(x);
 }
}
public static void main(String[] args)
{
 print1(3);
}

public static void print1(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  print2(x - 1);
  System.out.println(x);
 }
}

public static void print2(int x)
{
 if (x <= 0)
  System.out.println("Boom!");
 else
 {
  System.out.println(x);
  print3(x - 1);
  System.out.println(x);
 }
}

…
स्क्रीन आउटपुट: स्क्रीन आउटपुट:
3
2
1
Boom!
1
2
3
3
2
1
Boom!
1
2
3

"ठीक है। मुझे लगता है कि मैं समझता हूं। हमें रिकर्सन की आवश्यकता क्यों है?"

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

"या आपको उन फ़ाइलों की सूची प्रदर्शित करने की आवश्यकता है जो एक निर्देशिका और उसके सभी उपनिर्देशिकाओं में हैं। इसलिए आप एक ऐसी विधि लिखते हैं जो वर्तमान निर्देशिका की फ़ाइलों को प्रदर्शित करती है। फिर सभी उपनिर्देशिकाओं की फ़ाइलों को प्राप्त करने के लिए, आप एक का उपयोग करके अपनी विधि को कॉल करते हैं। अलग तर्क: एक उपनिर्देशिका।"

"उदाहरण के लिए:"

सभी फाइलों को एक निर्देशिका और उसकी उपनिर्देशिकाओं में प्रदर्शित करें
public static void main(String[] args)
{
 printAllFiles(new File("c:/windows/"));
}

public static void printAllFiles(File dir)
{
 for (File file : dir.listFiles())
 {
  if (file.isDirectory())
   printAllFiles(file);
  else
   System.out.println(file.getAbsolutePath());
 }
}

"पंक्ति 8 - हमें डीआईआर निर्देशिका में सभी फाइलों (और निर्देशिकाओं) की सूची मिलती है।"

"पंक्तियाँ 10-11 - यदि फ़ाइल वास्तव में एक निर्देशिका है, तो हम फिर से PrintAllFiles कहते हैं , लेकिन इस बार एक और तर्क के साथ: उपनिर्देशिका।"

"पंक्ति 13 - हम वर्तमान फ़ाइल का नाम प्रदर्शित करते हैं।"

"ठीक है। मुझे लगता है कि मैं समझ गया। धन्यवाद, बिलाबो।"