"Merhaba Amigo. Bugün Bilaabo sana özyinelemeden bahsedecek."

Yineleme - 1

Bildiğiniz gibi, Java'da bazı yöntemler diğer yöntemleri çağırır. Ek olarak, bir yöntem çağrıldığında, ona belirli argümanlar iletilir, ancak yöntemin yerel değişkenleri çalışırken belirli değerler alır.

"HI-hı."

"Ve bildiğiniz gibi, farklı yöntemlerin iç değişkenleri birbirinden bağımsızdır."

"HI-hı."

"Öyleyse bir yöntemin kendisini çağırdığı durumu hayal edin. Buna özyineleme denir. Örneğin:"

Örnek
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);
 }
}
Ekran çıkışı:
10
9
8
7
6
5
4
3
2
1
Boom!

"Yöntemin kodda kendisini çağırdığını görebiliyorum, ancak dürüst olmak gerekirse ne olduğunu anlamıyorum."

"Eh, farklı bir yöntem çağrıldığında olanla aynı şey."

"Hayır, değişkenlere ne olduğunu soruyorum? Değerleriyle mi? Ve yöntemden nasıl çıkacağız? Yoksa her şeyden birden mi çıkacağız?"

"Aman Allah'ım. Her şey çok daha basit. Kendini çağıran yöntemin defalarca çoğaltıldığını hayal edin. O zaman benzer bir durumla karşılaşırdık:"

Özyinelemeli yöntem çağrısı gerçekten ne oluyor
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);
 }
}
Ekran çıkışı: Ekran çıkışı:
3
2
1
Boom!
3
2
1
Boom!

"Başka bir deyişle, bir yöntem her çağrıldığında (kendi başına bile), bu yöntem için verileri depolayan yeni değişkenler oluşturulur. Paylaşılan değişken yoktur."

"Her çağrıda, yöntem argümanlarının yeni değerlerle başka bir kopyası bellekte oluşturulur. Eski yönteme döndüğümüzde değişkenleri orada kullanılır. Diğer bir deyişle, özyineleme sırasında aslında başka bir yöntemi çağırırız, ancak bizimkiyle aynı kod! "

"Anlıyorum. Peki bu tür yöntemlerden çıkmak nasıl oluyor? Belki bir örnek?"

"Tamam. Bir örnek bin kelimeye bedeldir. "İşte örneğiniz:"

Özyinelemeli yöntem çağrısı Özyinelemeli yöntem çağrısı
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);
 }
}
Ekran çıkışı: Ekran çıkışı:
3
2
1
Boom!
1
2
3
3
2
1
Boom!
1
2
3

"Tamam. Sanırım anladım. Neden özyinelemeye ihtiyacımız var?"

"Orijinal görevle aynı olan ayrı alt görevlere bölünebilen pek çok görev vardır. Örneğin, bir XML ağacının tüm öğelerini gözden geçirmeniz gerekir. Her öğenin birkaç alt öğesi olabilir ve bunların kendi alt öğeleri vardır. kendi alt öğeleri."

"Ya da bir dizinde ve tüm alt dizinlerinde bulunan dosyaların listesini görüntülemeniz gerekir. Böylece, geçerli dizinin dosyalarını görüntüleyen bir yöntem yazarsınız. Ardından, tüm alt dizinlerin dosyalarını almak için, yönteminizi bir kullanarak çağırırsınız. farklı bağımsız değişken: bir alt dizin."

"Örneğin:"

Bir dizindeki ve alt dizinlerindeki tüm dosyaları görüntüleyin
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());
 }
}

"Satır 8 – Dir dizinindeki tüm dosyaların (ve dizinlerin) listesini alıyoruz."

"Satır 10-11 – Dosya aslında bir dizin ise, o zaman printAllFiles'ı tekrar çağırırız , ancak bu sefer başka bir argümanla: alt dizin."

"Satır 13 – Geçerli dosyanın adını gösteriyoruz."

"Tamam. Sanırım anladım. Teşekkürler, Bilaabo."