Java - Karar Yapıları

Java - Karar Yapıları

Arkadaşlar merhaba,

Bugün java'da karar yapılarına göz atacağız umarım faydalı olur.

Karar yapıları girdilere bağlı olarak davranışın değişmesini sağlayan yapılardır.

If Statement

if mantıksal bir ifadeye bağlı olarak karar vermek için kullanılır.

if daima mantıksal bir ifade alır ve doğru ise sonraki cümle bloğu çalışır ,yanlış ise çalışmaz.

Her iki halde de akış if cümlesi ya da bloğundan sonra devam eder.

if ‘in mantıksal ifadesi doğru olmadığında çalışacak alternatif bir durum var ise else kullanılır

int ticketsTaken = 1;

if (ticketsTaken > 1)
            tickets++;
if (hourOfDay < 11)
    System.out.println("Good Morning"); // hourOfDay büyük dahi olsa GreetingCount  arttırlır !
greetingCount++;

Üstteki kod koşul karşılandığın da Good Morning yazdıracaktır , fakat greetingCount her zaman bir artacaktır.if ifadesinde herhangi bir blok olmadığı için altında ki tüm satırları değil ilk satırı koşula göre uygulayacaktır.

if koşulunu bloklar ile de yazabiliriz.Blok içinde ise if koşulu sağlandığında greetingCount değeri arttırılacaktır.

if(hourOfDay < 11) {
    System.out.println("Good Morning");
    greetingCount++;
}
if-else kullanımı

Gerekli şart sağlanmadığında çalışacak alternatif durum için else ifadesi kullanılabilir.

 if (hourOfDay < 11) {
            System.out.println("Good Morning");
    } else {
            System.out.println("Good Afternoon");
}

İki veya daha fazla şart için aşağıdaki gibi kullanılabilir.

Doğru olarak değerlendirilen bir if ifadesiyle karşılaşana kadar yürütmeye devam edecektir. İlk iki ifadeden hiçbiri doğru değilse, else bloğunun son kodunu yürütür. Karmaşık if ve else ifadeleri oluştururken akılda tutulması gereken bir şey, sıranın önemli olduğudur.

Sondaki else zorunlu değildir.

  if (hourOfDay < 11) {
            System.out.println("Good Morning");
  } else if (hourOfDay < 15) {
        System.out.println("Good Afternoon");
  } else {
            System.out.println("Good Evening");
}

Aşağıdaki kullanım hatalı bir kullanımdır , bir boolean ifadesi değildir.

int hourOfDay = 1;
 if(hourOfDay) { // DOES NOT COMPILE

}

Switch Statement

switch case, if else if else yapısının int ve String tipinden tekil değerler alan ifadeler için kullanılan halidir.

switch’ e geçilen int ya da String ifade, hangi case sabitesine eşitse o çalıştırılır. Eğer eşit değilse varsa default’tan sonrası break’e kadar onun ifadeleri çalıştırılır yoksa switch bloğunun çıkılır.

Derleyici hiç bir iki case sabitesinin aynı olmamasını sağlamaya çalışır.

switch’in ifadesi byte, short, char,int ya da String olmalıdır. Primitive tiplerin nesne (wrapper) Character, Byte, Short,Integer halleri de olabilir.

Boolean, long, float ve double öğelerinin wrapper halleri Boolean, Long, Float ve Double sınıfları gibi switch deyimlerinden hariç tutulduğuna dikkat edin.

switch’ e geçilen int ya da String ifade, hangi case sabitesine eşitse onun ifadeleri break’e kadar çalıştırılır.

Örneklere göz atalım.

switch (month) {} GEÇERLİ İFADE

int dayOfWeek = 5;
  switch(dayOfWeek) {
      default:
          System.out.println("Weekday");
         break;
    case 0:
        System.out.println("Sunday");
        break;
    case 6:
      System.out.println("Saturday");  
      break;
  }

// print Weekday

default değer weekday'dir. Weekday'den sonra break ifadesi olduğu için switch deyimi sonlanır.

break ifadesi kullanılmadığında ise akış otomatik olarak bir sonraki case'den yada default bloktan devam eder.

var dayOfWeek1 = 5;
        switch (dayOfWeek1) {
            case 0:
                System.out.println("Sunday");
            default:
                System.out.println("Weekday");
            case 6:
                System.out.println("Saturday");
                break;

 }

// Weekday
// Saturday

default ifadesi switch'in sonunda olursa çıktı 1 tane olur.

Eğer dayOfWeek1 değeri 6 olur ise çıktı sadece Saturday olacaktır.

default blok, switch deyimi içindeki konumundan bağımsız olarak, yalnızca switch deyimi için eşleşen bir case değeri yoksa çalışır. Eğer break deyimi olmayan bir case'den sonra default blok var ise yürütülür.

  • default değer almaz.
  • default en fazla bir tane olabilir.
  • Hiç case olmadan da default kullanılabilir.

case ifadesi kullanımı

Her case ifadesindeki değerler, switch değeriyle aynı veri türünün derleme zamanı sabit değerleri(constant) olmalıdır.

Bu, yalnızca aynı veri türündeki değişmezleri(constant), enum sabitlerini veya final constant variables'ları kullanabileceğiniz anlamına gelir. final constant ile, değişkenin final değiştirici ile işaretlenmesi ve bildirildiği aynı ifadede sabit (constant) bir değerle başlatılması gerekir.

Sabit değişken için final kullanılmalıdır.

Örneğin bir metot aynı değeri döndürse bile metot çağrısının sonucu çalışma zamanın da belirlendiği için sabit bir değişken olmadığı için bu şekilde kullanılamaz.

final int getCookies() {
        return 3;
}

void feed() {
    final int bananas = 1;
    int pear = 2;
    int numberOfAnimals = 3;
    final int cookies = getCookies();

    switch (numberOfAnimals) {
        case bananas:
        case pear: // DOES NOT COMPILE
        case getCookies(): // DOES NOT COMPILE
        case cookies: // DOES NOT COMPILE
        case 2 * 3:
  }

}

Cast Etme ve Yükseltme

Derleyici derleme zamanında short'dan int'e bir cast yapabilir.Çünkü 15 ifadesi short'a çevrilecek kadar küçültür. short bir derleme zamanı sabitesi olmasaydı buna izin verilmezdi. Aynı şekilde derleme zamanında 1+2 ifadesi int'den short'a çevrilebilir.

Öte yandan 1_000_000 ifadesi açık bir cast işlemi olmadan short'a sığmayacak kadar büyük bir değerdir , bu nedenle son case ifadesi derlenmez.

        short size = 4;
        final int small = 15; // constant olduğu için çalışır
        final int big = 1_000_000;

        switch (size) {
            case small:
            case 1 + 2:
            case big: // DOES NOT COMPILE
}

while

while, kendisinden sonra gelen mantıksal ifade doğru olduğu müddetçe,sonraki cümle ya da cümleler bloğunun çalışmasını sağlar. Mantıksal ifade false olduğunda while biter ve akış sonraki satırdan devam eder.

Yürütme sırasında, boolean ifadesi, döngünün her yinelemesinden önce değerlendirilir ve değerlendirme false döndürürse çıkar.

int counter = 0;

while (counter < 10){
       double price = counter * 10;
    counter++;
}
static int roomInBelly = 5;

    public static void eatCheese(int bitesOfCheese) {
        while (bitesOfCheese > 0 && roomInBelly > 0) {
            bitesOfCheese--;
            roomInBelly--;
        }
        System.out.println(bitesOfCheese + " pieces of cheese left");
    }

Do/While Statement

do while, do’dan sonra gelen cümle ya da cümle bloğunu, while’in mantıksal ifadesi true olduğu müddetçe çalıştırır.Mantıksal ifade false olduğunda do-while biter ve akış sonraki satırdan devam eder. while’dan farkı, cümle ya da bloğun en az bir kere çalışmasıdır, çünkü şart kontrolü sonda yapılmaktadır.

int lizard = 0;
   do {
            lizard++;
     } while (false);       // 1

for Loops

for, cümle ya da cümle bloğunu, tekrarlı olarak çalıştırmakta kullanılır.

Cümle ya da bloğun kaç defa çalıştırılacağı, başlangıç, değişim değerleri ve bitiş şartı ile belirlenir. Başlangıç değeri, bitiş şartı ve değişim eğeri, zorunlu değildir ama for için parantez zorunludur ve içinde iki tane ";" bulunmalıdır.

for (int i = 0; i < 10; i++)
            i = 0;
for (int j = 1; j < 10; j++)
            j--;
for (int k = 0; k < 10;)
            k++;

İlk örnekte, i her döngü sırasında 0'a sıfırlanır, ardından 1'e artırılır, ardından 0'a sıfırlanır...

İkinci örnekte j, 0'a düşürülür, ardından 1'e artırılır, ardından 0'a düşürülür ve bu şekilde devam eder.

Son örnek, döngüyü tam olarak 10 kez yürütür, bu nedenle biraz olağandışı olsa da geçerlidir.

for (var counter = 5; counter > 0; counter--) {
            System.out.print(counter + " ");
    }

Bu for döngüsü derlenmiyor gibi görünse de, aslında derlenecek ve sorunsuz çalışacaktır. Aslında aynı ifadeyi tekrar tekrar yazdıracak sonsuz bir döngüdür.

for (;;)
            System.out.println("Selam bro")
int x = 0;
for(int x = 4; x < 5; x++) {   // DOES NOT COMPILE
      System.out.print(x + " ");
}

Derleme olmama sebebi x'in döngüden önce zaten bildirildikten sonra başlatma bloğunda tekrarlanması ve derleyicinin yinelenen değişken bildirimi nedeniyle durmasıdır. Bu döngüyü, for döngüsünden x bildirimini aşağıdaki gibi kaldırarak düzeltebiliriz.

int x = 0;

for (x = 0; x < 5; x++) {
    System.out.print(x + " ");
}

Başlatma bloğundaki değişkenlerin tümü aynı türde olmalıdır.

int x = 0;
for (long y = 0, int z = 4; x < 5; x++) { // DOES NOT COMPILE
    System.out.print(y + " ");
}
for (long y = 0, x = 4; x < 5 && y < 10; x++, y++) {
  System.out.print(y + " ");
}
System.out.print(x); // DOES NOT COMPILE

Dikkat ederseniz, döngünün başlatma bloğunda x tanımlanır ve döngü sona erdikten sonra kullanılır. x'in kapsamı yalnızca döngü için olduğundan, onu döngü dışında kullanmak derleyici hatasına neden olur.

Multiple Kullanım

int x = 0;
for (long y = 0, z = 4; x < 5 && y < 10; x++, y++) {
            System.out.println("Y : " + y);
}
System.out.println("X : " + x);

Y : 0
Y : 1
Y : 2
Y : 3
Y : 4
X : 5

For-Each Loop

Her döngü için bildirim, bir başlatma bölümünden ve yinelenecek bir nesneden oluşur. for-each döngüsünün sağ tarafı aşağıdakilerden biri olmalıdır:

  • Bir Java dizisi,

  • Türü Java.lang.Iterable uygulayan bir nesne,

  • String ve StringBuilder, iterable uygulamaz ve for-each ifadesinin sağ tarafı olarak kullanılamaz.

Döngünün her yinelemesinde, ifadenin sol tarafındaki adlandırılmış değişkene, ifadenin sağ tarafındaki dizi veya collection'dan yeni bir değer atanır.

 List<String> values = new ArrayList<String>();
        values.add("Lisa");
        values.add("Kevin");
        values.add("Roger");
        for (var value: values) {
                   System.out.print(value + ", ");
   }

Bu örnekte, String adları bir dizi değildir ve bir öğe listesi tanımlamaz,bu nedenle derleyici String üzerinde nasıl yineleyeceğini bilmediğinden bir istisna atar.

String names = "Umut";

for (String name : names) { // DOES NOT COMPILE
    System.out.print(name + " ");
}

for-each ifadesi birçok durumda listelerle çalışmak için uygun olsa da, döngü yineleyici değişkenine erişimi gizler. Yalnızca isimler arasındaki virgülleri yazdırmak istersek, örneği aşağıdaki örnekte olduğu gibi bir standart for döngüsüne dönüştürebiliriz.

List<String> names1 = new ArrayList<String>();
        names1.add("Umut");
        names1.add("Ahmet");
        names1.add("Gökhan");
   for (int i = 0; i < names1.size(); i++) {
          String name = names1.get(i);
          if (i > 0) {
                System.out.print(", ");
            }
            System.out.print("name : " + name);
      }
    System.out.println();

Ayrıca for-each, Java 5'te tanıtıldığında, derleme zamanı geliştirmesi olarak eklendi.

Bu, Java'nın aslında derleme sırasında foreach döngüsünü bir standart for döngüsüne dönüştürdüğü anlamına gelir. Örneğin, ilk örnekte gördüğümüz gibi isimlerin bir String dizisi olduğunu varsayarsak, aşağıdaki iki döngü eşdeğerdir:

for(String name : names) {
      System.out.print(name + ", ");
}

for(int i=0; i < names.length; i++) {
    String name = names[i];
    System.out.print(name + ", ");
}

Nested (İç içe) Loops

İç içe döngü, while, do/while, for ve for-each döngülerini içeren başka bir döngü içeren bir döngülerdir.

int[][] myComplexArray = { { 5, 2, 1, 3 }, { 3, 9, 8, 9 }, { 5, 7, 12, 7 } };

  OUTER: for (int[] mySimpleArray : myComplexArray) {
            INNER: for (int i = 0; i < mySimpleArray.length; i++) {
                 System.out.print(mySimpleArray[i] + "\t");
        }
             System.out.println();
}

Opsiyonel olarak etiketli ve etiketsiz olarak kullanılabilirler.

Etiket, uygulama akışının ona atlamasına veya ondan ayrılmasına izin veren bir ifadenin başına isteğe bağlı bir işaretçidir.Üstteki örnekteki OUTER ve INNER ve bir etikettir.

Break ve Continue Deyimleri

break : switch, for , while ve do while ile kullanılır. break içinde bulunduğu yapıdan tamamen çıkmakta kullanılır.

Etiketsiz halinde break içinde bulunduğu tekrar yapısını tamamen kırar ve akış tekrar bloğunu takip eden cümleden devam eder.

Etiketli hali tipik olarak, içe içe tekrar yapılarının olduğu hallerde, etiket dıştaki bir tekrar yapısını gösterir ve bu şekilde dıştaki, etiketli tekrar kırılır.

int searchValue = 4;
int x = -1;
int y = -1;
    int[][] myArray = {{2, 4, 1, 5}, {5, 2, 1, 4}, {1, 4, 9, 7}};
     FIRST_LOOP:
        for (int i = 0; i < myArray.length; i++) {
            SECOND_LOOP:
            for (int j = 0; j < myArray[i].length; j++) {
                if (myArray[i][j] == searchValue) {
                    x = i;
                    y = j;
                    break FIRST_LOOP; //  eşleşen ilk değer bulunur bulunmaz üst döngü yapısındna ayrılır.
                    // break; // koşul karşılandığında iç döngüden çıkar.yani değeri içeren son iç döngünün ilk eşleşen değerine kadar devam eder.
                }

            }
            System.out.println(myArray);
        }

        if (x == -1 || y == -1) {
            System.out.println("Value " + searchValue + " not found");
        } else {
            System.out.println("Value " + searchValue + " found at: " + "(" + x + "," + y + ")");
        }

// Value 4 found at: (0,1)

continue, break’ın tersine, içinde bulunduğu tekrar yapısını kırmaz, sadece o adım için sonlandırır.

Etiketsiz halinde continue, içinde bulunduğu tekrar yapısının sadece o adımını sonlandırır ve akış aynı tekrar bloğunun bir sonraki adımından devam eder. Etiketli halinde continue‘dan sonra bir etiket kullanılır. Bu etiket, bir tekrar yapısının göstermelidir.

EXAMPLE : for (int i = 1; i < 10; i++ ){
    if (i == 5){
        continue EXAMPLE;
        //continue;
    }
    System.out.println("i : " + i);
}

return

return, bir metottan, o metotun çağırıldığı ortama dönüş yapmak için kullanılır.

Metodun bir değer döndürmediği durumlarda metot arayüzünde void kullanılır.

return’den sonra hiç bir kod olamaz.

Metot bir değer döndürüyorsa, değerin tipi ile metotun dönüş tipi uyumlu olmalıdır.

double total(){
            .......
            return;
}