"สวัสดี Amigo วันนี้ Bilaabo จะบอกคุณเกี่ยวกับการเรียกซ้ำ"

การเรียกซ้ำ - 1

อย่างที่คุณทราบ ใน Java บางเมธอดเรียกเมธอดอื่น นอกจากนี้ เมื่อมีการเรียกใช้เมธอด จะมีการส่งอาร์กิวเมนต์เฉพาะไปให้เมธอด แต่ตัวแปรโลคัลของเมธอดจะรับค่าบางอย่างในขณะที่รัน

"เอ่อ-ฮะ"

"และอย่างที่คุณทราบ ตัวแปรภายในของเมธอดต่างๆ นั้นไม่ขึ้นต่อกัน"

"เอ่อ-ฮะ"

"ลองจินตนาการถึงสถานการณ์ที่เมธอดเรียกตัวเอง ซึ่งเรียกว่าการวนซ้ำ ตัวอย่างเช่น:"

ตัวอย่าง
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 แต่ละองค์ประกอบสามารถมีองค์ประกอบย่อยได้หลายรายการ และพวกมันก็มี องค์ประกอบลูกของตัวเอง "

"หรือคุณต้องการแสดงรายการไฟล์ที่อยู่ในไดเร็กทอรีและไดเร็กทอรีย่อยทั้งหมด ดังนั้นคุณจึงเขียนเมธอดที่แสดงไฟล์ของไดเร็กทอรีปัจจุบัน จากนั้นเพื่อรับไฟล์ของไดเร็กทอรีย่อยทั้งหมด คุณเรียกเมธอดของคุณโดยใช้ a อาร์กิวเมนต์ที่แตกต่างกัน: ไดเร็กทอรีย่อย"

"ตัวอย่างเช่น:"

แสดงไฟล์ทั้งหมดในไดเร็กทอรีและไดเร็กทอรีย่อย
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 – เราได้รับรายชื่อไฟล์ทั้งหมด (และไดเร็กทอรี) ในไดเร็กทอรี dir"

"บรรทัดที่ 10-11 – หากไฟล์เป็นไดเร็กทอรีจริง เราจะเรียกprintAllFilesอีกครั้ง แต่คราวนี้ใช้อาร์กิวเมนต์อื่น: ไดเร็กทอรีย่อย"

"บรรทัดที่ 13 – เราแสดงชื่อไฟล์ปัจจุบัน"

"ตกลง ฉันคิดว่าฉันเข้าใจแล้ว ขอบคุณ บิลาโบ"