Java default method çakışması, bir sınıfın aynı imzaya sahip iki farklı default methodu iki ayrı interface’ten miras almasıyla oluşur. Java hangi method gövdesini seçmesi gerektiğini otomatik olarak varsayamaz; bu nedenle sınıftan açık bir tercih yapmasını bekler. Çözüm genellikle sınıf içinde ilgili methodu yeniden yazarak davranışı belirlemektir.
default methodlar, interface’lere yalnızca davranış bildirimi değil, hazır bir davranış da eklemeyi sağlar. Ancak iki bağımsız interface aynı method adı, parametre listesi ve uyumlu dönüş türüyle farklı gövdeler tanımlarsa seçim belirsiz hâle gelir. Java bilgi seviyeni ölçmek için ücretsiz Java bilgi testlerini kullanarak interface ve kalıtım konularındaki temelini kontrol edebilirsin.
Default method çakışması neden belirsizlik oluşturur?
Aşağıdaki örnekte Yazdirilabilir ve Loglanabilir interface’leri aynı mesajGoster() methodunu tanımlar. İki methodun adı, parametre listesi ve dönüş türü aynıdır; fakat gövdeleri farklı davranır.
interface Yazdirilabilir {
default void mesajGoster() {
System.out.println("Yazdırılabilir mesaj");
}
}
interface Loglanabilir {
default void mesajGoster() {
System.out.println("Log mesajı");
}
}
class Rapor implements Yazdirilabilir, Loglanabilir {
// Burada mesajGoster() yeniden yazılmadı.
}
public class Main {
public static void main(String[] args) {
Rapor rapor = new Rapor();
rapor.mesajGoster();
}
}
Rapor sınıfı iki interface’i de uyguladığı için iki farklı mesajGoster() gövdesini miras alır. Program çalıştırıldığında Java’nın “Yazdırılabilir mesaj”ı mı yoksa “Log mesajı”nı mı göstereceğine dair örtük bir seçim yapması gerekir. Fakat bu seçim, programcının amacı bilinmeden güvenilir biçimde yapılamaz.
Bu nedenle derleyici, sınıfın belirsizliği açıkça gidermesini ister. Buradaki sorun methodların kullanılamaması değil, aynı çağrı için birden fazla geçerli davranış bulunmasıdır. Bir interface mesajı ekrana yazmayı, diğeri kayıt tutmayı amaçlıyor olabilir. Java bunlardan birini rastgele seçerse programın beklenmeyen bir davranış üretme ihtimali doğar.
Çakışmayı çözmek için Rapor sınıfında mesajGoster() methodu yeniden yazılabilir. Sınıf böylece kendi davranışını tanımlar veya interface’lerden birinin varsayılan davranışını açıkça seçer. Hangi yaklaşımın doğru olduğuna karar vermeden önce çakışmanın gerçekten aynı imzadan kaynaklanıp kaynaklanmadığını, interface’lerin birbirleriyle ilişkisini ve sınıf hiyerarşisinde daha öncelikli somut bir method bulunup bulunmadığını incelemek gerekir.
Çakışmayı çözmeden önce hangi üç noktayı incelemelisiniz?

Her default method çakışmasında doğrudan override yazmak yerine aşağıdaki teşhis sırasını izlemek, gereksiz kod eklenmesini önler:
- Method imzası gerçekten aynı mı?
Önce method adını, parametre türlerini ve sayısını karşılaştır. Java’da method imzasını belirleyen temel unsur ad ve parametre listesidir. Dönüş türü de uyumlu olmalıdır; aksi durumda konu yalnızca default method çakışması değil, ayrı bir method tanımlama veya uyumluluk problemi olabilir.
- Interface’ler arasında kalıtım ilişkisi var mı?
İki interface birbirinden türemişse durum, tamamen bağımsız iki interface’in çakışmasından farklıdır. Daha özel olan alt interface, üst interface’teki davranışı geçersiz kılabilir. Bu yüzden interface’lerin doğrudan bağımsız mı olduğu, yoksa birinin diğerini genişletip genişletmediği kontrol edilmelidir.
- Sınıfta veya üst sınıfta somut method var mı?
Uygulayan sınıfın kendisinde ya da miras aldığı sınıfta aynı imzaya sahip somut bir method bulunup bulunmadığını incele. Sınıf hiyerarşisindeki somut method, interface’ten gelen default davranışlar karşısında öncelikli olabilir. Böyle bir method zaten varsa yeni bir override yazmak gereksiz olabilir.
Bu üç kontrol, “hangi method neden seçilemiyor?” sorusunu imza, interface kalıtımı ve sınıf önceliği sırasıyla yanıtlamanı sağlar.
InterfaceName.super.method() ile belirli davranışı seçme

Bir sınıf, aynı imzaya sahip default method içeren iki bağımsız interface’i uyguladığında Java hangi davranışın kullanılacağını kendiliğinden seçemez. Bu durumda sınıf, çakışan methodu override etmeli ve hangi interface davranışlarının kullanılacağını açıkça belirtmelidir.
interface Printer {
default void printStatus() {
System.out.println("Yazıcı durumu: hazır");
}
}
interface Logger {
default void printStatus() {
System.out.println("Log kaydı: durum yazdırıldı");
}
}
class Device implements Printer, Logger {
@Override
public void printStatus() {
Printer.super.printStatus();
Logger.super.printStatus();
}
}
public class Main {
public static void main(String[] args) {
Device device = new Device();
device.printStatus();
}
}
Burada Device sınıfı hem Printer hem de Logger interface’ini doğrudan uyguluyor. İki interface’te de printStatus() methodu bulunduğu için sınıf içinde override zorunlu hâle geliyor. Printer.super.printStatus() yazıcıdaki, Logger.super.printStatus() ise kayıt tutma davranışındaki varsayılan methodu çağırır.
InterfaceName.super.method() sözdizimi, sınıfın doğrudan uyguladığı uygun bir interface’in default davranışını seçmek için kullanılır. Böylece yalnızca tek bir davranışı çağırabilir, iki davranışı sırayla çalıştırabilir veya bu çağrıların arasına sınıfa özgü işlemler ekleyebilirsin. Bu ayrım, özellikle birebir Java yazılım dersleri sırasında interface çakışmalarını adım adım teşhis ederken önem kazanır.
Örneğin yukarıdaki kodun beklenen konsol çıktısı şöyledir:
Yazıcı durumu: hazır
Log kaydı: durum yazdırıldı
Sınıftaki somut method neden default method’dan önce gelir?
Java’nın method seçimindeki temel kurallardan biri şudur: Sınıfın içinde tanımlanan somut method, aynı imzaya sahip bir interface default methodundan önceliklidir. Bu nedenle sınıf, interface’lerden gelen davranışlarla aynı imzaya sahip kendi methodunu zaten içeriyorsa her interface default’unu çağırmak için ayrıca override yazmak zorunda değildir.
Örneğin Device sınıfında public void printStatus() methodu bulunuyorsa, nesne üzerinden yapılan printStatus() çağrısında sınıftaki method çalışır. Interface’lerdeki default methodlar otomatik olarak devreye girmez. Ancak sınıf iki davranışı birleştirmek, yalnızca belirli bir interface’in davranışını seçmek veya özel bir çıktı üretmek istiyorsa açık bir override yazmalıdır.
Burada bağımsız interface’ler arasındaki çakışma ile interface kalıtımını birbirinden ayırmak gerekir. Bir interface diğerinden türediğinde, türeyen interface daha özel bir default method sağlayabilir. Bu durum, iki bağımsız interface’in aynı methodu sunarak oluşturduğu belirsizlikten farklıdır. Dolayısıyla önce interface’ler arasında bir kalıtım ilişkisi olup olmadığını, ardından sınıfın aynı imzaya sahip somut bir method içerip içermediğini kontrol etmek doğru teşhis sırasıdır.
Gereksiz override yazmamak için hata önleme kontrol listesi
Default method çakışmalarında amaç, her interface için otomatik olarak override yazmak değil, Java’nın neden hangi davranışı seçemediğini doğru teşhis etmektir. Aşağıdaki kontrol listesi, gereksiz kod eklemeden çakışmayı çözmene yardımcı olur:
- Method imzasını karşılaştır: Method adının, parametre sayısının, parametre türlerinin ve dönüş tipinin gerçekten aynı olup olmadığını kontrol et. Yalnızca benzer görünen method’lar her zaman aynı imzaya sahip değildir.
- Interface’ler arasındaki kalıtım ilişkisini incele: Bir interface diğerinden türemişse, daha özel interface’in default method’u öncelik kazanabilir. Bu nedenle interface’leri yalnızca sınıfın doğrudan uyguladığı yapılar olarak değil, aralarındaki miras ilişkileriyle birlikte değerlendir.
- Sınıfta mevcut somut method’u ara: Sınıfta aynı imzaya sahip somut bir method varsa bu method, interface’lerdeki default method’lardan önce gelir. Böyle bir durumda sırf interface’lerde default method bulunduğu için yeni bir override yazmak gerekmeyebilir.
- Gerçekten seçim yapman gerekip gerekmediğini belirle: İki bağımsız interface aynı imzaya sahip default method sunuyorsa sınıfın hangi davranışı kullanacağını açıkça belirlemesi gerekir. Ancak yalnızca bir default method etkiliyse veya sınıfta zaten somut method varsa gereksiz override ekleme.
- Gerekirse tek bir davranışı açıkça çağır: İki davranıştan birini seçiyorsan override içinde
InterfaceName.super.method()kullan. Böylece seçimin nedenini kod üzerinde görünür hâle getirirsin. - Davranışları bilinçli biçimde birleştir: Her iki interface’in davranışı da gerekli olabilir. Bu durumda iki default method’u çağırıp aralarındaki sırayı ve olası tekrarları bilinçli biçimde yönet.
- Beklenen çıktıyla doğrula: Kodun derlenmesi tek başına yeterli değildir. Method’un kaç kez çalıştığını, çıktı sırasını ve seçilen davranışın beklediğin sonucu üretip üretmediğini kontrol et.
Örneğin bir sınıfın hem Readable hem de Writable interface’ini uyguladığını düşün. İkisi de aynı imzaya sahip bir default method içeriyor, fakat sınıfın bu davranışa ihtiyacı yoksa otomatik override yazmak yalnızca gereksiz kod ve bakım yükü oluşturur. Buna karşılık iki davranış arasında seçim yapılması gerekiyorsa override zorunlu hâle gelir.
Çakışmanın kaynağını bulmak zorlaşıyorsa, konuyu yalnızca hata mesajını kapatacak şekilde değil, neden-sonuç ilişkisiyle incelemek önemlidir. Bu tür durumlarda doğrudan hata teşhisine odaklanan birebir özel ders ile kendi kod yapın üzerinden ilerlemek daha anlaşılır bir çalışma yöntemi sağlayabilir.
Sık Sorulan Sorular
İki interface aynı default method’a sahipse override yazmak her zaman zorunlu mudur?
Hayır. Interface’ler arasında kalıtım ilişkisi varsa daha özel interface’in method’u öncelik kazanabilir. Ayrıca sınıfta aynı imzaya sahip somut bir method bulunuyorsa bu method default method’ların önüne geçer. İki bağımsız interface arasında belirsizlik oluşuyorsa override yazmak gerekir.
InterfaceName.super.method() sözdizimi ne zaman kullanılabilir?
Bir sınıfın uyguladığı interface’in default method’unda bulunan davranışı açıkça seçmek istediğinde kullanılabilir. Bu sözdizimi, sınıfın hangi interface davranışını çağırdığını belirtir ve genellikle override edilen method’un gövdesi içinde kullanılır.
Sınıfta aynı imzaya sahip somut method varsa interface default method’u yine de çağrılır mı?
Normal method çağrısında sınıftaki somut method kullanılır. Interface’in default method’unu ayrıca çalıştırmak istiyorsan uygun interface üzerinden açıkça çağırman gerekir; aksi hâlde sınıftaki method önceliklidir.
Interface’ler arasında kalıtım ilişkisi olması çakışma çözümünü nasıl etkiler?
Daha özel interface’in aynı imzaya sahip default method’u, daha genel interface’teki davranışa göre öncelik kazanabilir. Bu nedenle çözüm üretmeden önce interface’lerin birbirinden türeyip türemediğini kontrol etmek, gereksiz override yazmanı önleyebilir.
Doğru çözüm için önce method imzalarını, kalıtım ilişkilerini ve sınıftaki somut method’ları incele; ardından yalnızca gerçekten gereken davranışı açıkça seç veya bilinçli biçimde birleştir.