← Kursa Dön
📄 Text · 12 min

Karşılaştırma ve Mantıksal Operatörler

Programlama karar vermek demek. "Kullanıcı giriş yapmış mı?", "Bakiye yeterli mi?", "Yaş 18'den büyük mü?" — bu soruların cevabı hep true ya da false. Karşılaştırma ve mantıksal operatörler bu kararları almanı sağlar.


Karşılaştırma Operatörleri

İki değeri karşılaştırır, sonuç her zaman boolean (true veya false) döner.

OperatörAnlamıÖrnekSonuç
==Eşit mi?5 == 5true
!=Eşit değil mi?5 != 3true
>Büyük mü?5 > 3true
<Küçük mü?5 < 3false
>=Büyük veya eşit mi?5 >= 5true
<=Küçük veya eşit mi?3 <= 5true
int yas = 25;
int limit = 18;

System.out.println(yas == limit);  // false
System.out.println(yas != limit);  // true
System.out.println(yas > limit);   // true
System.out.println(yas >= 25);     // true
System.out.println(yas < 30);      // true
System.out.println(yas <= 18);     // false

Karşılaştırma Sonuçlarını Saklama

Karşılaştırma sonucu bir boolean değişkene atanabilir:

int puan = 85;
boolean gecti = puan >= 60;
boolean basarili = puan >= 80;

System.out.println("Geçti mi: " + gecti);      // true
System.out.println("Başarılı mı: " + basarili); // true

== Tuzağı: Primitive vs Nesne

Primitive tiplerde == değer karşılaştırır:

int a = 5;
int b = 5;
System.out.println(a == b); // true — değerler eşit

Ama nesnelerde == referans (adres) karşılaştırır:

String s1 = new String("test");
String s2 = new String("test");
System.out.println(s1 == s2);      // false! Farklı nesneler
System.out.println(s1.equals(s2)); // true — içerik aynı

⚠️ Altın kural: Primitive tiplerde == kullan, nesnelerde equals() kullan. Bu farkı String dersinde detaylıca gördük.


Mantıksal Operatörler

Birden fazla koşulu birleştirmek için mantıksal operatörler kullanılır.

OperatörAnlamıAçıklama
&&VE (AND)İkisi de true ise true
`\\`VEYA (OR)En az biri true ise true
!DEĞİL (NOT)true → false, false → true

&& (AND) — İkisi de Doğruysa

int yas = 25;
boolean ehliyet = true;

boolean surebilir = (yas >= 18) && ehliyet;
System.out.println(surebilir); // true

// Her iki koşul da true olmalı
System.out.println(true && true);   // true
System.out.println(true && false);  // false
System.out.println(false && true);  // false
System.out.println(false && false); // false

Bunu şöyle düşün: Kapıdan geçmek için hem anahtar hem şifre lazım. Biri eksikse giremezsin.

Doğruluk Tablosu (Truth Table)

&& ve || için tüm kombinasyonları bir görelim:

ABA && BA \\B!A
truetruetruetruefalse
truefalsefalsetruefalse
falsetruefalsetruetrue
falsefalsefalsefalsetrue

Bu tablo her zaman geçerli. Ezberlemek yerine mantığını anla:

  • && → "İkisi de olacak" → Bir tane false varsa false

  • || → "Biri yeter" → Bir tane true varsa true

  • ! → "Tersini al"

|| (OR) — En Az Biri Doğruysa

boolean ogrenci = true;
boolean emekli = false;

boolean indirimliMi = ogrenci || emekli;
System.out.println(indirimliMi); // true

// En az bir koşul true olmalı
System.out.println(true || true);   // true
System.out.println(true || false);  // true
System.out.println(false || true);  // true
System.out.println(false || false); // false

! (NOT) — Tersini Al

boolean aktif = true;
System.out.println(!aktif); // false

boolean bos = false;
System.out.println(!bos);   // true

// if ile kullanım
if (!aktif) {
    System.out.println("Kullanıcı aktif değil");
}

Short-Circuit Evaluation — Kısa Devre Değerlendirme

Bu çok önemli bir kavram. && ve || operatörleri tembel çalışır — sonucu kesinleştirecek kadar değerlendirir, gerisine bakmaz.

&& ile Short-Circuit

&&'de sol taraf false ise sağ taraf hiç çalışmaz:

String isim = null;

// Güvenli! isim null ise sağ taraf çalışmaz
if (isim != null && isim.length() > 3) {
    System.out.println("Uzun isim");
}

// Tehlikeli! & (tek) short-circuit yapmaz
// if (isim != null & isim.length() > 3) { // NullPointerException!

Neden? false && herhangibirsey her zaman false döner. Sol taraf false ise sağ tarafa bakmanın anlamı yok. Java bunu bilir ve sağ tarafı çalıştırmaz.

|| ile Short-Circuit

||'de sol taraf true ise sağ taraf hiç çalışmaz:

boolean onbellek = true;

// Eğer önbellekte varsa veritabanına sormaz
if (onbellek || veritabaninaBak()) {
    System.out.println("Veri bulundu");
}
// onbellek true ise veritabaninaBak() çağrılmaz bile!
// Pratik kullanım: null kontrolü
String deger = ayarGetir("tema");
String tema = (deger != null) ? deger : "varsayilan";

💡 Short-circuit hem güvenlik sağlar (null kontrolü) hem performans kazandırır (gereksiz işlem yapmaz). && ve || kullanırken sol tarafa "ucuz" veya "koruyucu" koşulu koy.

& ve | (Tek) — Short-Circuit Yapmaz

Tek & ve | da mantıksal operatör olarak kullanılabilir ama short-circuit yapmazlar — her iki tarafı da her zaman değerlendirir:

int x = 0;
boolean sonuc = (x != 0) & (10 / x > 2); // ArithmeticException!
// && olsaydı sol taraf false olduğu için sağ çalışmazdı

Pratikte her zaman `&&` ve `||` kullan. Tek & ve | mantıksal amaçla kullanma (bunlar bitwise operatör olarak daha anlamlı — bitwise dersinde göreceğiz).


Koşulları Birleştirme

Gerçek dünyada birden fazla koşulu birleştirmen gerekir:

int yas = 25;
double bakiye = 5000.0;
boolean vipUye = false;

// Kredi onayı: yaş >= 18 VE (bakiye >= 10000 VEYA vip üye)
boolean krediOnay = (yas >= 18) && (bakiye >= 10000 || vipUye);
System.out.println("Kredi onay: " + krediOnay); // false
// Bilet fiyatı hesaplama
int yas2 = 12;
boolean indirim = (yas2 < 7) || (yas2 >= 65);

if (yas2 < 7) {
    System.out.println("Ücretsiz");
} else if (yas2 <= 18 || yas2 >= 65) {
    System.out.println("İndirimli");
} else {
    System.out.println("Tam fiyat");
}

Operatör Önceliği

Mantıksal operatörlerin öncelik sırası:

ÖncelikOperatör
1 (en yüksek)! (NOT)
2&& (AND)
3 (en düşük)`\\` (OR)
// && önce değerlendirilir
boolean sonuc = true || false && false;
// Aslında: true || (false && false) = true || false = true

// Parantezle açık yaz
boolean acik = (true || false) && false; // true && false = false

⚠️ Parantez koy! Önceliği ezberlemek yerine parantez kullanmak hem güvenli hem okunabilir.


Ternary Operatör (? :)

if-else'in kısa hali. Tek satırda koşullu değer atamak için kullanılır.

Sözdizimi: koşul ? dogruDeger : yanlisDeger

int yas = 20;
String durum = (yas >= 18) ? "Yetişkin" : "Çocuk";
System.out.println(durum); // "Yetişkin"

// if-else karşılığı:
String durum2;
if (yas >= 18) {
    durum2 = "Yetişkin";
} else {
    durum2 = "Çocuk";
}
// Pratik kullanımlar
int a = 10, b = 20;
int max = (a > b) ? a : b;
System.out.println("Max: " + max); // 20

double fiyat = 100;
double indirim = vipUye ? 0.20 : 0.05;
double sonFiyat = fiyat * (1 - indirim);
// Null kontrolü
String isim = null;
String gosterilecek = (isim != null) ? isim : "Misafir";
System.out.println("Hoş geldin, " + gosterilecek); // "Hoş geldin, Misafir"

İç İçe Ternary — Yapma!

// KÖTÜ — okunmuyor
String sonuc = (puan >= 90) ? "A" : (puan >= 80) ? "B" : (puan >= 70) ? "C" : "F";

// İYİ — if-else kullan
String sonuc;
if (puan >= 90) sonuc = "A";
else if (puan >= 80) sonuc = "B";
else if (puan >= 70) sonuc = "C";
else sonuc = "F";

Ternary operatörü basit, tek koşullu durumlarda kullan. İç içe yazma — okunabilirliği mahveder.


De Morgan Kuralları

Koşulları tersine çevirirken işe yarayan matematik kuralları:

OrijinalEşdeğer
!(a && b)`!a \\!b`
`!(a \\b)`!a && !b
int yas = 25;
boolean uye = true;

// Bu ikisi aynı şey:
boolean sonuc1 = !(yas >= 18 && uye);
boolean sonuc2 = (yas < 18) || !uye;
System.out.println(sonuc1 == sonuc2); // true

De Morgan'ı genellikle karmaşık koşulları sadeleştirmek veya daha okunabilir yapmak için kullanırsın.

// Zor okunan:
if (!(x < 0 || x > 100)) { ... }

// Daha açık:
if (x >= 0 && x <= 100) { ... }

Koşulları Okunabilir Yazmak — Guard Clauses

Koşullar karmaşıklaşınca okunabilirlik düşer. Bunu çözmenin birkaç yolu var:

Guard Clause Pattern (Erken Çıkış)

İç içe if yazmak yerine, olumsuz durumları en başta ele al ve erken çık:

// KÖTÜ — "piramit" kodu, iç içe koşullar
public double indirimHesapla(Kullanici k, Urun u) {
    if (k != null) {
        if (k.isAktif()) {
            if (u != null) {
                if (u.getFiyat() > 100) {
                    return u.getFiyat() * 0.1;
                }
            }
        }
    }
    return 0;
}

// İYİ — guard clause ile düz akış
public double indirimHesapla(Kullanici k, Urun u) {
    if (k == null || !k.isAktif()) return 0;
    if (u == null || u.getFiyat() <= 100) return 0;
    
    return u.getFiyat() * 0.1;
}

İkinci versiyon çok daha okunabilir. "Şu koşullar sağlanmıyorsa çık" mantığı ile her engeli teker teker ele alıyorsun.

Koşulları Metoda Çıkar

// KÖTÜ — uzun koşul
if (kullanici.getYas() >= 18 && kullanici.isEmailDogrulanmis() 
    && kullanici.getBakiye() >= urun.getFiyat() 
    && !kullanici.isKaraListede() && urun.isStokta()) {
    satin_al();
}

// İYİ — metotlara böl
if (satinAlabilirMi(kullanici, urun)) {
    satin_al();
}

private boolean satinAlabilirMi(Kullanici k, Urun u) {
    boolean yetiskin = k.getYas() >= 18;
    boolean dogrulanmis = k.isEmailDogrulanmis();
    boolean yeterliPara = k.getBakiye() >= u.getFiyat();
    boolean engelliDegil = !k.isKaraListede();
    boolean stokVar = u.isStokta();
    
    return yetiskin && dogrulanmis && yeterliPara && engelliDegil && stokVar;
}

switch ile Karşılaştırma

Birden fazla == kontrolü gerektiğinde switch daha temiz olabilir:

// if-else zinciri
int gun = 3;
String gunAdi;

if (gun == 1) gunAdi = "Pazartesi";
else if (gun == 2) gunAdi = "Salı";
else if (gun == 3) gunAdi = "Çarşamba";
else if (gun == 4) gunAdi = "Perşembe";
else if (gun == 5) gunAdi = "Cuma";
else if (gun == 6) gunAdi = "Cumartesi";
else if (gun == 7) gunAdi = "Pazar";
else gunAdi = "Geçersiz";

// switch expression (Java 14+)
String gunAdi2 = switch (gun) {
    case 1 -> "Pazartesi";
    case 2 -> "Salı";
    case 3 -> "Çarşamba";
    case 4 -> "Perşembe";
    case 5 -> "Cuma";
    case 6 -> "Cumartesi";
    case 7 -> "Pazar";
    default -> "Geçersiz";
};

Pratik Örnek: Kullanıcı Doğrulama

public class KullaniciDogrulama {
    public static void main(String[] args) {
        String kullaniciAdi = "ahmet_42";
        String sifre = "Guclu123!";
        int girisDenemesi = 2;
        boolean hesapKilitli = false;
        
        // Kullanıcı adı kontrolü
        boolean adGecerli = kullaniciAdi != null 
            && kullaniciAdi.length() >= 3 
            && kullaniciAdi.length() <= 20;
        
        // Şifre kontrolü
        boolean sifreGecerli = sifre != null 
            && sifre.length() >= 8;
        
        // Hesap kontrolü
        boolean hesapAktif = !hesapKilitli 
            && girisDenemesi < 5;
        
        // Giriş yapabilir mi?
        boolean girisYapabilir = adGecerli && sifreGecerli && hesapAktif;
        
        String mesaj = girisYapabilir 
            ? "Giriş başarılı!" 
            : "Giriş reddedildi.";
        
        System.out.println(mesaj);
        System.out.println("Ad geçerli: " + adGecerli);
        System.out.println("Şifre geçerli: " + sifreGecerli);
        System.out.println("Hesap aktif: " + hesapAktif);
    }
}

Boolean İfadelerini Temiz Yazma

1. Gereksiz karşılaştırma yapma:

// Kötü
if (aktif == true) { ... }
if (bos == false) { ... }

// İyi
if (aktif) { ... }
if (!bos) { ... }

2. Koşulları anlamlı değişkenlere ata:

// Kötü — ne kontrol ediliyor?
if (yas >= 18 && bakiye >= 1000 && !kilitli && deneme < 3) { ... }

// İyi — okunabilir
boolean yetiskin = yas >= 18;
boolean yeterliPara = bakiye >= 1000;
boolean hesapAktif = !kilitli && deneme < 3;

if (yetiskin && yeterliPara && hesapAktif) { ... }

3. Pozitif koşul yaz:

// Kötü — çift negatif, kafa karıştırıcı
if (!aktifDegil) { ... }

// İyi
if (aktif) { ... }

Karşılaştırma Operatörleri ile Sıralama

compareTo() metodu nesneleri sıralamak için kullanılır. Karşılaştırma operatörlerinin nesne versiyonu diyebilirsin:

Integer a = 10;
Integer b = 20;

int sonuc = a.compareTo(b);
// sonuc < 0 → a küçük
// sonuc == 0 → eşit
// sonuc > 0 → a büyük

System.out.println(a.compareTo(b)); // -1 (a < b)
System.out.println(b.compareTo(a)); // 1  (b > a)
System.out.println(a.compareTo(a)); // 0  (eşit)
// String sıralama
String s1 = "elma";
String s2 = "armut";
System.out.println(s1.compareTo(s2)); // pozitif (e > a)

Koşullu İfadeler ile Kullanım

Karşılaştırma ve mantıksal operatörler en çok if, while, for yapılarında kullanılır:

// Basit if
int sicaklik = 35;
if (sicaklik > 30) {
    System.out.println("Çok sıcak!");
}

// if-else if-else zinciri
int puan = 75;
if (puan >= 90) {
    System.out.println("AA");
} else if (puan >= 80) {
    System.out.println("BA");
} else if (puan >= 70) {
    System.out.println("BB");
} else if (puan >= 60) {
    System.out.println("CB");
} else {
    System.out.println("FF");
}
// while döngüsünde koşul
int sayac = 0;
while (sayac < 5 && !iptalEdildi) {
    islemYap();
    sayac++;
}

// for döngüsünde koşul
for (int i = 0; i < liste.size() && !bulundu; i++) {
    if (liste.get(i).equals(aranan)) {
        bulundu = true;
    }
}

instanceof Operatörü

Java 16+ ile gelen pattern matching'li instanceof:

Object obj = "Merhaba";

// Eski yol
if (obj instanceof String) {
    String s = (String) obj;
    System.out.println(s.length());
}

// Yeni yol — Java 16+ pattern matching
if (obj instanceof String s) {
    System.out.println(s.length()); // s otomatik cast edilmiş
}

// Negatif koşulda da çalışır
if (!(obj instanceof String s)) {
    System.out.println("String değil");
    return;
}
// Buradan sonra s kullanılabilir
System.out.println(s.toUpperCase());

Null-Safe Karşılaştırma

Java'da null en büyük düşmanlardan biri. Karşılaştırma yaparken null kontrolü şart:

// Objects.equals() — null-safe
import java.util.Objects;

String a = null;
String b = "test";

// a.equals(b) → NullPointerException!
System.out.println(Objects.equals(a, b)); // false — güvenli!
System.out.println(Objects.equals(null, null)); // true

// Sıralama için null-safe comparator
import java.util.Comparator;

Comparator<String> nullSafe = Comparator.nullsLast(Comparator.naturalOrder());
System.out.println(nullSafe.compare("a", null)); // negatif (a önce)
System.out.println(nullSafe.compare(null, "a")); // pozitif (null sona)

Pratik Örnek: Harf Notu Hesaplama

public class HarfNotu {
    public static String notHesapla(int puan) {
        if (puan < 0 || puan > 100) {
            return "Geçersiz puan!";
        }
        
        // Ternary zinciri (kısa ama okunabilir sınırda)
        return (puan >= 90) ? "AA" :
               (puan >= 85) ? "BA" :
               (puan >= 80) ? "BB" :
               (puan >= 75) ? "CB" :
               (puan >= 70) ? "CC" :
               (puan >= 65) ? "DC" :
               (puan >= 60) ? "DD" : "FF";
    }
    
    public static void main(String[] args) {
        int[] puanlar = {95, 82, 67, 45, 71, 88};
        
        for (int puan : puanlar) {
            String not = notHesapla(puan);
            boolean gecti = !not.equals("FF");
            System.out.printf("Puan: %d → %s %s%n", 
                puan, not, gecti ? "✓" : "✗");
        }
    }
}

Pratik Örnek: Aralık Kontrolü

public class AralikKontrol {
    // Bir sayının aralıkta olup olmadığını kontrol et
    static boolean aralikta(int sayi, int min, int max) {
        return sayi >= min && sayi <= max;
    }
    
    // İki aralığın kesişip kesişmediğini kontrol et
    static boolean kesisiyor(int min1, int max1, int min2, int max2) {
        return min1 <= max2 && min2 <= max1;
    }
    
    public static void main(String[] args) {
        // Yaş grubu kontrolü
        int yas = 25;
        
        boolean cocuk = aralikta(yas, 0, 12);
        boolean genç = aralikta(yas, 13, 17);
        boolean yetiskin = aralikta(yas, 18, 64);
        boolean yasli = yas >= 65;
        
        System.out.println("Çocuk: " + cocuk);     // false
        System.out.println("Genç: " + genç);       // false
        System.out.println("Yetişkin: " + yetiskin); // true
        System.out.println("Yaşlı: " + yasli);     // false
        
        // Saat aralığı kesişimi
        boolean kesisim = kesisiyor(9, 12, 11, 15);
        System.out.println("Kesişiyor: " + kesisim); // true
    }
}

Sık Yapılan Hatalar

1. = ile == karıştırmak:

int x = 5;
// if (x = 10) { } // DERLEME HATASI! (atama, karşılaştırma değil)
if (x == 10) { }    // Doğru

Java'da bu genellikle derleme hatası verir (C/C++'tan farklı olarak). Ama boolean ile dikkatli ol:

boolean b = false;
// if (b = true) { } // Derlenir! Ama atama yapar, karşılaştırma değil
if (b == true) { }   // Karşılaştırma (ama gereksiz, if (b) yeterli)

2. Floating point karşılaştırması:

double a = 0.1 + 0.2;
if (a == 0.3) { } // false! Hassasiyet sorunu
if (Math.abs(a - 0.3) < 1e-10) { } // Doğru yol

3. Short-circuit'ı unutmak:

String s = null;
// if (s.length() > 0 && s != null) { } // NullPointerException!
if (s != null && s.length() > 0) { }    // Güvenli — sıra önemli

4. Integer wrapper karşılaştırması:

Integer a = 200;
Integer b = 200;
if (a == b) { } // false! Referans karşılaştırma
if (a.equals(b)) { } // true — doğru yol
// Veya unbox et:
if (a.intValue() == b.intValue()) { } // true

5. boolean karşılaştırmasında gereksiz == true:

// Gereksiz
if (aktif == true) { }
if (bos == false) { }

// Temiz
if (aktif) { }
if (!bos) { }

Özet

  • Karşılaştırma operatörleri (==, !=, <, >, <=, >=) her zaman boolean döner

  • Nesneleri == ile karşılaştırma — referansı değil içeriği karşılaştırmak için equals() kullan

  • && (VE) ve || (VEYA) short-circuit yapar — sol taraf yeterliyse sağ tarafa bakmaz

  • Short-circuit sayesinde null kontrolünü sola koyarak güvenli kod yazabilirsin

  • Ternary operatör (? :) basit koşullu atamalar için iyidir ama iç içe kullanma

  • Koşulları anlamlı boolean değişkenlere atayarak okunabilirliği artır

  • Guard clause pattern'ı ile iç içe if'lerden kaçın — olumsuz durumları erken ele al

  • Objects.equals() ile null-safe karşılaştırma yap


Mülakat Soruları

S: == ile equals() farkı? C: == primitive'lerde değer, nesnelerde referans (adres) karşılaştırır. equals() nesne içeriğini karşılaştırır. String karşılaştırmasında her zaman equals() kullan.

S: Short-circuit evaluation nedir? C: && ve || operatörlerinin sol tarafın sonucuna göre sağ tarafı değerlendirmemesi. false && X → X hiç çalışmaz. true || X → X hiç çalışmaz. Null kontrolü ve performans için önemli.

S: De Morgan kuralları nedir? C: !(A && B) = !A || !B ve !(A || B) = !A && !B. Koşulların tersini alırken kullanılır.