Core Java Bilginizi Test Edin: Kapsamlı Bir Soru ve Cevap Rehberi
Java Geliştiricileri İçin Bilgi Tazeleyici: Core Java Quiz Neden Önemli?
Java, yazılım dünyasının en köklü ve yaygın olarak kullanılan programlama dillerinden biridir. Geniş uygulama alanları, platform bağımsızlığı ve güçlü ekosistemi sayesinde milyonlarca geliştirici tarafından tercih edilmektedir. Bir Java geliştiricisi olarak kariyerinizde ilerlemek, yeni projelere dahil olmak veya teknik mülakatlarda başarılı olmak için Core Java konularına hakim olmak vazgeçilmezdir. Temel Java bilgisi, dilin derinliklerine inebilmenizin, daha karmaşık çerçeveleri (Spring, Hibernate vb.) anlayabilmenizin ve verimli, hatasız kod yazabilmenizin temelini oluşturur.
Bu makale, Core Java bilginizi test etmek, eksiklerinizi belirlemek ve önemli kavramları pekiştirmek amacıyla hazırlanmıştır. Her bir bölüm, belirli bir Core Java konusuna odaklanacak, konuya dair bir soru sunacak ve ardından detaylı bir açıklama ile doğru cevabı verecektir. Bu rehber, hem yeni başlayanlar hem de deneyimli geliştiriciler için değerli bir kaynak olacaktır. Haydi, Java bilginizi sınamaya başlayalım!
Java Temelleri ve Ortamı
Java’nın temel yapı taşları, dilin nasıl çalıştığını anlamak için kritik öneme sahiptir. JVM’den veri tiplerine, operatörlerden String yönetimine kadar bu bölüm, Java’nın çekirdek bileşenlerine odaklanmaktadır.
JVM, JRE, JDK Farkları
Soru: Bir Java uygulamasını derlemek ve çalıştırmak için hangi bileşenlere ihtiyacınız vardır? JVM, JRE ve JDK arasındaki temel farkları açıklayınız.
Cevap: Bir Java uygulamasını derlemek ve çalıştırmak için JDK (Java Development Kit) bileşenine ihtiyacınız vardır. JDK, Java uygulamaları geliştirmek için gereken tüm araçları (derleyici – javac, hata ayıklayıcı – jdb vb.) ve aynı zamanda JRE’yi (Java Runtime Environment) içerir. JRE ise, bir Java uygulamasını çalıştırmak için gerekli olan sanal makineyi (JVM – Java Virtual Machine) ve temel kütüphaneleri barındırır. Kısaca, JDK geliştirme için, JRE çalıştırma için, JVM ise Java bytecode’unu yorumlayıp yürüten soyut bir makinedir. Yani, JDK hem geliştirme hem de çalıştırma yeteneği sunarken, JRE yalnızca çalıştırma yeteneği sağlar ve JVM ise bu çalıştırma işleminin temelini oluşturur.
İlkel Veri Tipleri ve Referans Tipleri
Soru: Java’da int ve Integer arasındaki fark nedir? Ne zaman hangisini tercih etmelisiniz?
Cevap: int, Java’daki sekiz ilkel veri tipinden biridir ve doğrudan bellek üzerinde değer saklar. Hafıza kullanımı açısından daha verimlidir ve varsayılan değeri 0’dır. Integer ise, int ilkel tipinin sarmalayıcı (wrapper) sınıfıdır ve bir nesnedir. Nesne olduğu için null değeri alabilir ve koleksiyon çerçevesinde (örneğin ArrayList) ilkel tiplerin kullanılamadığı durumlarda tercih edilir. int daha çok performans kritik hesaplamalar için uygunken, Integer nesne gerektiren durumlarda, örneğin generic tiplerle veya null değerlerin mümkün olduğu yerlerde kullanılır. Java 5’ten itibaren gelen autoboxing/unboxing özelliği sayesinde bu iki tip arasında otomatik dönüşüm yapılabilir.
String Değişmezliği (Immutability)
Soru: Java’da String nesneleri neden değişmez (immutable) olarak kabul edilir? Bunun avantajları nelerdir?
Cevap: Java’da String nesneleri değişmezdir, yani bir String nesnesi oluşturulduktan sonra içeriği değiştirilemez. Bir String üzerinde yapılan her “değişiklik” aslında bellekte yeni bir String nesnesi oluşturulmasına neden olur. Bunun başlıca avantajları şunlardır: Güvenlik: Veritabanı bağlantı bilgileri, şifreler gibi hassas veriler String olarak saklandığında, değişmezlik sayesinde bu verilerin referansları farklı metotlara geçtiğinde dahi orijinal içeriğin manipüle edilemeyeceği garantilenir. Thread Güvenliği: Değişmez nesneler, birden fazla iş parçacığı tarafından güvenle paylaşılabilir, çünkü durumları asla değişmez. Bu da senkronizasyon mekanizmalarına olan ihtiyacı azaltır. Performans: String havuzu (String Pool) sayesinde aynı içeriğe sahip String‘ler tek bir bellek konumunu paylaşabilir, bu da bellek kullanımını optimize eder.
final Anahtar Kelimesi
Soru: Java’da final anahtar kelimesinin bir değişken, bir metot ve bir sınıf için kullanıldığında ne anlama geldiğini açıklayınız.
Cevap: final anahtar kelimesi Java’da üç farklı bağlamda kullanılır:
finalbir değişken: Bir değişkenfinalolarak tanımlandığında, değeri yalnızca bir kez atanabilir ve daha sonra değiştirilemez. Genellikle sabitler için kullanılır (örneğinfinal int MAX_VALUE = 100;).finalbir metot: Bir metotfinalolarak tanımlandığında, alt sınıflar tarafından ezilemez (override edilemez). Bu, metodun davranışının alt sınıflarda değiştirilmemesini garanti eder.finalbir sınıf: Bir sınıffinalolarak tanımlandığında, o sınıftan başka bir sınıf miras alamaz (extend edilemez). Bu, sınıfın tasarımının ve davranışının tamamen kontrol altında tutulmasını sağlar (örneğinjava.lang.Stringsınıfıfinal‘dır).
Nesne Yönelimli Programlama (OOP) İlkeleri
Java, nesne yönelimli bir programlama dilidir ve OOP’nin dört temel ilkesi (Kapsülleme, Miras Alma, Çok Biçimlilik, Soyutlama) dilin gücünü ve esnekliğini oluşturur. Bu bölüm, bu ilkelerin derinlemesine anlaşılmasına odaklanmaktadır.
Kapsülleme (Encapsulation)
Soru: Kapsülleme nedir ve Java’da nasıl sağlanır? Bir örnekle açıklayınız.
Cevap: Kapsülleme, nesne yönelimli programlamanın temel ilkelerinden biridir ve verileri (alanlar/field’lar) ve bu veriler üzerinde işlem yapan metotları (davranışlar) tek bir birim altında birleştirme ve dış dünyadan gizleme sürecidir. Java’da kapsülleme, genellikle sınıfın alanlarını private erişim belirleyicisi ile tanımlayarak ve bu alanlara erişimi ve manipülasyonu public metotlar (getter ve setter metotları) aracılığıyla sağlayarak gerçekleştirilir. Bu yaklaşım, nesnenin iç durumunun kontrolsüz erişime karşı korunmasını sağlar ve dışarıdan yalnızca tanımlanmış arayüzler aracılığıyla etkileşim kurulmasına izin verir. Örneğin, bir Hesap sınıfında bakiye alanı private tanımlanır ve getBakiye() ve setBakiye() metotları ile erişim sağlanır.
Miras Alma (Inheritance)
Soru: Java’da çoklu miras (multiple inheritance) neden desteklenmez? Alternatif olarak hangi mekanizmalar kullanılır?
Cevap: Java, sınıflar arasında doğrudan çoklu mirası desteklemez. Yani, bir sınıf birden fazla üst sınıftan miras alamaz. Bunun temel nedeni “Elmas Problemi” (Diamond Problem) olarak bilinen belirsizlik durumudur: Eğer bir sınıf iki farklı üst sınıftan miras alır ve bu üst sınıfların her ikisinde de aynı isimde bir metot varsa, alt sınıfın hangi metodun uygulamasını kullanacağı belirsiz hale gelir. Bu durum derleyici için kafa karıştırıcıdır ve çalışma zamanında öngörülemeyen davranışlara yol açabilir. Java, bu karmaşıklığı önlemek amacıyla tekli miras ilkesini benimsemiştir. Çoklu mirasın sağladığı faydaları elde etmek için Java, arayüzleri (interfaces) kullanır. Bir sınıf birden fazla arayüzü uygulayabilir ve böylece farklı davranış setlerini birleştirebilir. Java 8 ile birlikte arayüzlerde varsayılan metotların (default methods) eklenmesi, bu alternatifin gücünü daha da artırmıştır.
Çok Biçimlilik (Polymorphism)
Soru: Metot ezme (method overriding) ve metot aşırı yükleme (method overloading) arasındaki farkları açıklayınız. Her ikisi de çok biçimliliğin hangi türüne örnek teşkil eder?
Cevap:
- Metot Ezme (Overriding): Bir alt sınıfın, üst sınıfında tanımlanmış bir metodu kendi ihtiyacına göre yeniden tanımlamasıdır. Metot imzası (isim, parametre sayısı ve tipleri) aynı kalır, ancak implementasyonu değişir. Çalışma zamanı çok biçimliliğine (runtime polymorphism) örnektir.
- Metot Aşırı Yükleme (Overloading): Aynı sınıf içinde veya miras alınan bir sınıfta, aynı isme sahip ancak farklı parametre listelerine (sayı, tip veya sıralama) sahip birden fazla metot tanımlanmasıdır. Dönüş tipi farklı olabilir ancak tek başına yeterli değildir. Derleme zamanı çok biçimliliğine (compile-time polymorphism) örnektir.
Kısacası, overriding miras hiyerarşisinde metot davranışını değiştirirken, overloading aynı sınıfta farklı parametrelerle aynı isimli metotlar oluşturur.
Soyut Sınıflar (Abstract Classes) ve Arayüzler (Interfaces)
Soru: Soyut sınıflar ve arayüzler arasındaki temel farklar nelerdir? Ne zaman hangisini kullanmayı tercih etmelisiniz?
Cevap: Hem soyut sınıflar hem de arayüzler soyutlama sağlamak için kullanılır, ancak önemli farkları vardır:
- Soyut Sınıflar: Kısmen implement edilmiş sınıflardır. Hem soyut (implementasyonu olmayan) hem de somut (implementasyonu olan) metotlar içerebilirler. Alanlar tanımlayabilir, kurucuları olabilir ve yalnızca tek bir soyut sınıftan miras alınabilir. Bir “is-a” ilişkisini (bir nesnenin başka bir nesne türü olması) ifade etmek için idealdir.
- Arayüzler: Java 8 öncesinde sadece soyut metotlar ve sabitler içerebilirlerdi. Java 8 sonrası varsayılan ve statik metotları da içerebilirler. Alanları varsayılan olarak
public static final‘dır. Kurucuları olamaz. Bir sınıf birden fazla arayüzü uygulayabilir. Bir “has-a” ilişkisini (bir nesnenin belirli bir yeteneğe sahip olması) veya bir davranış sözleşmesini tanımlamak için idealdir.
Soyut sınıf, ortak bir temel implementasyon sağlarken, arayüz tamamen davranış sözleşmesi tanımlar.
İstisna Yönetimi (Exception Handling)
Hata yönetimi, sağlam ve güvenilir Java uygulamaları geliştirmek için kritik bir beceridir. Bu bölüm, istisna türlerini, yönetim mekanizmalarını ve en iyi uygulamaları ele almaktadır.
Checked ve Unchecked Exceptions
Soru: Java’da “checked” (kontrol edilmiş) ve “unchecked” (kontrol edilmemiş) istisnalar arasındaki fark nedir? Birer örnek veriniz.
Cevap:
- Checked Exceptions (Kontrol Edilmiş İstisnalar): Derleme zamanında kontrol edilen istisnalardır. Java derleyicisi, bu tür istisnaların yakalanmasını (
try-catchbloğu ile) veya metodun imzasında belirtilmesini (throwsanahtar kelimesi ile) zorunlu kılar. Bu istisnalar genellikle programın kontrolü dışındaki, ancak kurtarılabilir durumları (örneğin, dosya bulunamadı –FileNotFoundException, SQL hatası –SQLException) temsil eder. - Unchecked Exceptions (Kontrol Edilmemiş İstisnalar): Çalışma zamanında (runtime) meydana gelen istisnalardır ve derleyici tarafından kontrol edilmezler. Genellikle programcı hatalarını (örneğin, sıfıra bölme –
ArithmeticException, dizi sınırları dışına çıkma –ArrayIndexOutOfBoundsException,nullreferansına erişim –NullPointerException) temsil ederler. Bu istisnaları yakalamak zorunlu değildir, ancak programın daha sağlam olması için bazılarını yakalamak faydalı olabilir.
try-catch-finally Bloğu
Soru: try-catch-finally bloğunun her bir kısmının amacını açıklayınız. finally bloğu her zaman çalışır mı? İstisnai durumlar nelerdir?
Cevap:
try: Potansiyel olarak istisna fırlatabilecek kod bloğunu içerir.catch:trybloğunda fırlatılan belirli bir istisna türünü yakalamak ve işlemek için kullanılır. Birden fazlacatchbloğu olabilir.finally:trybloğu tamamlandıktan veya bir istisna yakalandıktan sonra her zaman yürütülen kod bloğudur. Genellikle kaynakları (dosya akışları, veritabanı bağlantıları vb.) kapatmak gibi temizlik işlemleri için kullanılır.
Evet, finally bloğu genellikle her zaman çalışır. Ancak, System.exit() çağrısı yapılması, JVM’nin çökmesi (örneğin bellek yetersizliği gibi ciddi bir hata – OutOfMemoryError) veya iş parçacığının aniden sonlandırılması gibi çok nadir ve istisnai durumlarda finally bloğu yürütülmeyebilir.
Java Koleksiyon Çerçevesi (Collections Framework)
Java Koleksiyon Çerçevesi, veri yapılarını depolamak ve manipüle etmek için güçlü ve esnek bir dizi arayüz ve sınıf sağlar. Bu bölüm, en sık kullanılan koleksiyonları ve onların özelliklerini ele almaktadır.
List, Set, Map Arayüzleri
Soru: Java Koleksiyon Çerçevesi’ndeki List, Set ve Map arayüzlerinin temel özelliklerini ve kullanım amaçlarını karşılaştırınız.
Cevap:
List: Sıralı bir eleman koleksiyonunu temsil eder. Elemanlar eklenme sırasına göre tutulur ve indeks tabanlı erişim mümkündür. Tekrar eden elemanlara izin verir. Örnek implementasyonlar:ArrayList,LinkedList. Kullanım amacı: Elemanların sırasının önemli olduğu ve tekrar eden elemanların olabileceği durumlar (örneğin, bir öğrenci listesi).Set: Tekil elemanlardan oluşan bir koleksiyonu temsil eder. Tekrar eden elemanlara izin vermez ve elemanların sırası genellikle garanti edilmez (LinkedHashSethariç). Örnek implementasyonlar:HashSet,TreeSet. Kullanım amacı: Tekil elemanların tutulması gereken durumlar (örneğin, benzersiz ID’lerin kümesi).Map: Anahtar-değer çiftleri şeklinde elemanları saklayan bir koleksiyondur. Her anahtar tekil olmalı, ancak değerler tekrar edebilir. Anahtarlar ve değerler arasında bir eşleme sağlar. Örnek implementasyonlar:HashMap,TreeMap. Kullanım amacı: Bir anahtar aracılığıyla değerlere hızlı erişim gereken durumlar (örneğin, bir sözlük veya kullanıcı profilleri).
ArrayList ve LinkedList Karşılaştırması
Soru: ArrayList ve LinkedList arasındaki temel performans farkları nelerdir? Hangi senaryolarda hangisi tercih edilmelidir?
Cevap:
ArrayList: Dahili olarak dinamik bir dizi (array) kullanır. Elemanlara indeksle erişim (get(index)) çok hızlıdır (O(1)). Ancak ortadan eleman ekleme veya silme işlemi maliyetlidir (O(n)), çünkü diğer elemanların kaydırılması gerekir. Listenin sonuna eleman ekleme genellikle hızlıdır (amortized O(1)). Büyük veri setlerinde sık sık indeks tabanlı erişim ve sonuna ekleme yapılıyorsa tercih edilir.LinkedList: Çift yönlü bağlı liste (doubly linked list) yapısını kullanır. Elemanlara indeksle erişim yavaştır (O(n)), çünkü listenin başından veya sonundan başlayarak elemanlar tek tek gezilir. Ancak listenin herhangi bir yerinden eleman ekleme veya silme işlemi hızlıdır (O(1)), çünkü sadece düğüm referansları güncellenir. Sık sık ortadan eleman ekleme veya silme yapılıyorsa tercih edilir.
HashMap ve TreeMap Farkları
Soru: HashMap ve TreeMap arasındaki temel farklar nelerdir? Null anahtar ve değer kabul etme durumlarını karşılaştırınız.
Cevap:
HashMap: Anahtar-değer çiftlerini depolamak için hash tablosu kullanır. Elemanların sırasını garanti etmez; eklenme sırası veya doğal sıralama yoktur. Hızlı ekleme, silme ve arama işlemleri sunar (ortalama O(1)). Bir tanenullanahtar ve birden fazlanulldeğer kabul eder.TreeMap: Anahtar-değer çiftlerini depolamak için kırmızı-siyah ağaç (red-black tree) yapısını kullanır. Elemanları anahtarların doğal sıralamasına göre veya özel birComparatorile sıralanmış bir şekilde tutar. Ekleme, silme ve arama işlemleriHashMap‘e göre biraz daha yavaştır (O(log n)).nullanahtar kabul etmez, ancak birden fazlanulldeğer kabul eder.
HashMap performansa odaklanırken, TreeMap sıralı verilere ihtiyaç duyulan durumlarda tercih edilir.
Çoklu İş Parçacığı (Multithreading) ve Eşzamanlılık
Çoklu iş parçacığı, Java’nın eşzamanlı programlama yeteneklerinin merkezindedir. Bu bölüm, iş parçacığı oluşturma, senkronizasyon ve yaşam döngüsü gibi konuları ele almaktadır.
Thread Sınıfı ve Runnable Arayüzü
Soru: Java’da bir iş parçacığı (thread) oluşturmanın iki temel yolu nedir? Hangi yöntem genellikle tercih edilir ve neden?
Cevap: Java’da bir iş parçacığı oluşturmanın iki temel yolu vardır:
Threadsınıfını genişleterek (extending):java.lang.Threadsınıfından miras alan bir sınıf oluşturulur verun()metodu ezilir.Runnablearayüzünü uygulayarak (implementing):java.lang.Runnablearayüzünü uygulayan bir sınıf oluşturulur verun()metodu implemente edilir. Ardından buRunnablenesnesi birThreadnesnesine parametre olarak verilir.
Genellikle Runnable arayüzünü uygulamak tercih edilir. Bunun temel nedeni, Java’da bir sınıfın yalnızca tek bir sınıftan miras alabilmesidir (tekli miras). Eğer Thread sınıfını genişletirseniz, sınıfınız başka bir sınıftan miras alma yeteneğini kaybeder. Runnable arayüzünü kullanmak, kodun daha esnek olmasını sağlar ve iş parçacığı mantığını (run() metodu) iş parçacığının kendisinden (Thread nesnesi) ayırarak daha temiz bir tasarım sunar. Ayrıca, aynı Runnable nesnesini birden fazla Thread nesnesine vererek aynı görevi farklı iş parçacıklarında çalıştırmak da mümkündür.
Senkronizasyon ve Deadlock
Soru: Java’da synchronized anahtar kelimesinin amacı nedir? Deadlock (kilitlenme) nedir ve nasıl önlenebilir?
Cevap: synchronized anahtar kelimesi, Java’da çoklu iş parçacıklı ortamlarda paylaşılan kaynaklara erişimi kontrol etmek ve iş parçacığı güvenliğini sağlamak için kullanılır. Bir metot veya kod bloğu synchronized olarak işaretlendiğinde, aynı anda yalnızca bir iş parçacığı o metoda veya bloğa erişebilir. Bu, veri tutarsızlığını ve yarış koşullarını (race conditions) önler.
Deadlock (kilitlenme), iki veya daha fazla iş parçacığının birbirlerinin serbest bırakmasını beklediği, ancak hiçbirinin serbest bırakma yapmadığı ve dolayısıyla hiçbir iş parçacığının ilerleyemediği bir durumdur. Örneğin, İş Parçacığı A, Kaynak 1’i tutarken Kaynak 2’yi bekler ve İş Parçacığı B, Kaynak 2’yi tutarken Kaynak 1’i beklerse deadlock oluşur. Deadlock’u önlemek için stratejiler şunlardır: kilitlerin tutarlı bir sırayla alınması, kilitlerin timeout ile alınması (belirli bir süre sonra bırakılması), kaynakların tek bir işlemde elde edilmesi veya kilit hiyerarşisi kullanılması.
Java 8 ve Sonrası Yenilikler
Java 8, dilin evriminde önemli bir dönüm noktası olmuştur. Lambda ifadeleri, Stream API ve Optional gibi özellikler, kod yazma şeklimizi büyük ölçüde değiştirmiştir. Bu bölüm, bu yeniliklerin bazılarını incelemektedir.
Lambda İfadeleri
Soru: Lambda ifadeleri Java’ya ne gibi faydalar sağlamıştır? Basit bir örnekle açıklayınız.
Cevap: Lambda ifadeleri (lambda expressions), Java 8 ile birlikte gelen ve fonksiyonel programlama tarzını dile taşıyan önemli bir özelliktir. Temel amacı, tek metotlu arayüzlerin (fonksiyonel arayüzler) anonim implementasyonlarını daha kısa ve okunabilir bir sözdizimiyle yazmayı sağlamaktır.
Faydaları:
- Daha Az Kod: Anonim iç sınıflara göre çok daha az kod yazmayı gerektirir.
- Okunabilirlik: Kodun amacını daha net bir şekilde ifade eder.
- Paralel İşleme: Stream API ile birlikte kullanılarak veri koleksiyonları üzerinde paralel işlemeyi kolaylaştırır.
Örnek: Bir List‘i sıralamak için eski yöntemle Comparator anonim sınıfı yazmak yerine:
Collections.sort(list, (a, b) -> a.compareTo(b));
Bu, a ve b parametrelerini alan ve a.compareTo(b) sonucunu döndüren basit bir fonksiyondur.
Stream API
Soru: Java Stream API’nin temel amacı nedir ve koleksiyonlar üzerinde ne tür işlemleri kolaylaştırır?
Cevap: Java Stream API, Java 8 ile tanıtılan ve koleksiyonlar (veya diğer veri kaynakları) üzerinde işlevsel stil işlemleri gerçekleştirmek için güçlü bir soyutlama sağlayan bir yapıdır. Temel amacı, veri işleme mantığını daha bildirimsel, daha özlü ve potansiyel olarak paralel bir şekilde ifade etmeyi kolaylaştırmaktır.
Stream API, üç ana türde işlem sunar:
- Kaynak (Source): Bir koleksiyon, dizi, I/O kanalı veya bir üretici fonksiyonu gibi veri kaynağı.
- Ara İşlemler (Intermediate Operations): Bir stream üzerinde dönüştürme veya filtreleme gibi işlemler yapar ve yeni bir stream döndürür. Bu işlemler tembeldir (lazy), yani terminal bir işlem çağrılana kadar yürütülmezler (örneğin
filter(),map(),sorted()). - Terminal İşlemler (Terminal Operations): Bir stream üzerinde nihai bir işlem yapar ve bir sonuç (tek bir değer, bir koleksiyon veya bir yan etki) üretir. Bu işlemler stream’i kapatır ve bir daha kullanılamaz hale getirir (örneğin
forEach(),collect(),reduce(),count()).
Stream API, özellikle büyük veri setleri üzerinde filtreleme, dönüştürme, gruplama ve özetleme gibi işlemleri daha verimli ve okunabilir bir şekilde yapmayı sağlar, hatta paralel işlemeye olanak tanır.
Genel En İyi Uygulamalar ve Mülakat İpuçları
Core Java’yı bilmek kadar, bu bilgiyi doğru ve etkili bir şekilde kullanmak da önemlidir. Bu bölüm, sıkça karşılaşılan pratik konulara ve mülakatlara hazırlık ipuçlarına değinmektedir.
equals() ve hashCode() Metotları
Soru: Bir sınıfta equals() metodunu ezdiğinizde (override ettiğinizde) neden hashCode() metodunu da ezmeniz gerekir? Bu metotlar arasındaki kontrat nedir?
Cevap: Java’da bir sınıfta equals() metodunu ezdiğinizde, hashCode() metodunu da ezmeniz kesinlikle gereklidir. Bu, Object sınıfı tarafından tanımlanan ve tüm Java sınıflarının uyması gereken temel bir kontrattır:
- Eğer iki nesne
equals()metoduna göre eşitse, bu iki nesneninhashCode()metotları da aynı tam sayı değerini döndürmelidir. - Eğer iki nesnenin
hashCode()metotları aynı tam sayı değerini döndürüyorsa, bu iki nesneninequals()metoduna göre eşit olması gerekmez (çakışmalar olabilir), ancak eşit olma olasılığı artırılmalıdır. - Eğer iki nesne
equals()metoduna göre eşit değilse, bu iki nesneninhashCode()metotlarının farklı tam sayı değerleri döndürmesi gerekmez.
Bu kontratın ihlal edilmesi, özellikle HashMap, HashSet gibi hash tabanlı koleksiyonlarda nesnelerin doğru şekilde çalışmamasına, bulunamamasına veya beklenmeyen davranışlara yol açar. Çünkü bu koleksiyonlar önce hashCode() ile bir bölme (bucket) belirler, ardından equals() ile nesneleri karşılaştırır.
Garbage Collection
Soru: Java’da Garbage Collection (Çöp Toplama) nasıl çalışır? Geliştiriciler olarak Garbage Collector’ı doğrudan nasıl kontrol edebiliriz?
Cevap: Java’da Garbage Collection (GC), artık kullanılmayan (hiçbir aktif referansı olmayan) nesneleri otomatik olarak bellekten temizleyen bir süreçtir. Geliştiricilerin manuel bellek yönetimi yapmasına gerek kalmadan bellek sızıntılarını önlemeyi ve programın daha güvenli çalışmasını sağlamayı amaçlar. GC, genellikle arka planda çalışır ve “mark-and-sweep” (işaretle ve süpür) gibi algoritmalar kullanır: önce erişilebilir nesneleri işaretler, sonra erişilemeyen nesneleri bellekten temizler.
Geliştiriciler olarak Garbage Collector’ı doğrudan ve kesin olarak kontrol edemeyiz. Java Sanal Makinesi (JVM) ne zaman GC’nin çalışacağına kendisi karar verir. Ancak System.gc() veya Runtime.getRuntime().gc() metotlarını çağırarak bir GC çalıştırma isteğinde bulunabiliriz. Bu bir istek olduğu için, JVM bu isteği göz ardı edebilir ve GC’yi hemen çalıştırmayabilir. En iyi uygulama, GC’ye müdahale etmeye çalışmak yerine, nesnelerin referanslarını doğru yöneterek ve bellek sızıntılarını önleyerek temiz ve verimli kod yazmaya odaklanmaktır.
Sonuç: Sürekli Öğrenme ve Gelişim
Bu makalede Core Java’nın birçok temel ve ileri düzey konusunu kapsayan sorular ve detaylı cevaplar sunduk. JVM’den OOP ilkelerine, istisna yönetiminden koleksiyonlara ve Java 8 yeniliklerine kadar geniş bir yelpazede bilginizi tazelediniz ve muhtemelen yeni şeyler öğrendiniz.
Core Java, sadece bir programlama dilinin temeli olmanın ötesinde, yazılım geliştirmenin temel prensiplerini anlamak için bir kapıdır. Bu tür quizler ve bilgi testleri, öğrenme sürecinin önemli bir parçasıdır. Bilgiyi pekiştirmenize, eksiklerinizi görmenize ve kendinize güveninizi artırmanıza yardımcı olurlar. Unutmayın, yazılım geliştirme dünyası sürekli değişiyor ve gelişiyor. Bu nedenle, sürekli öğrenmeye, pratik yapmaya ve en güncel teknolojileri takip etmeye devam etmek başarının anahtarıdır.
Umarız bu rehber, Core Java bilginizi güçlendirmenize ve bir sonraki teknik mülakatınızda veya projenizde size yardımcı olmuştur. Başarılar dileriz!