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ör | Anlamı | Örnek | Sonuç |
|---|---|---|---|
== | Eşit mi? | 5 == 5 | true |
!= | Eşit değil mi? | 5 != 3 | true |
> | Büyük mü? | 5 > 3 | true |
< | Küçük mü? | 5 < 3 | false |
>= | Büyük veya eşit mi? | 5 >= 5 | true |
<= | Küçük veya eşit mi? | 3 <= 5 | true |
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); // falseKarşı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şitAma 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ör | Anlamı | 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); // falseBunu şö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:
| A | B | A && B | A \ | \ | B | !A |
|---|---|---|---|---|---|---|
| true | true | true | true | false | ||
| true | false | false | true | false | ||
| false | true | false | true | true | ||
| false | false | false | false | true |
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ı:
| Öncelik | Operatö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ı:
| Orijinal | Eş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); // trueDe 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ğruJava'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 yol3. Short-circuit'ı unutmak:
String s = null;
// if (s.length() > 0 && s != null) { } // NullPointerException!
if (s != null && s.length() > 0) { } // Güvenli — sıra önemli4. 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()) { } // true5. 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 zamanbooleandönerNesneleri
==ile karşılaştırma — referansı değil içeriği karşılaştırmak içinequals()kullan&&(VE) ve||(VEYA) short-circuit yapar — sol taraf yeterliyse sağ tarafa bakmazShort-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 kullanmaKoş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.
AI Asistan
Sorularını yanıtlamaya hazır