C# ve Java yakın akrabalardır. İkisi de C tarzı sözdizimine sahip, statik tipli, nesne yönelimli ve çöp toplayıcılı dillerdir; ikisi de bir sanal makine için bytecode'a derlenir ve ikisi de büyük backend sistemlerinde kullanılır. C#, 2002'de kısmen Microsoft'un Java'ya cevabı olarak çıktı ve yirmi yılda ikisi birbirinden özellikler ödünç aldı (lambda'lar, generics, record'lar, pattern matching). Birini bilen bir geliştirici diğerini neredeyse hemen okuyabilir.
Günlük işte önemli olan farklar daha küçük ve daha belirgindir. Bu sayfa onları kodla ele alır: çalıştırabileceğiniz C# parçaları ve karşılaştırma için statik bloklarda Java.
Bir bakışta
| C# | Java | |
|---|---|---|
| Yaratıcısı | Microsoft (2002) | Sun Microsystems (1995), şimdi Oracle |
| Çalışma zamanı | CLR (.NET), IL'i yerel koda derler | JVM, bytecode'u yerel koda derler |
| Platformlar | Windows, Linux, macOS | Windows, Linux, macOS |
| Property'ler | Yerleşik: public int Age { get; set; } | Getter ve setter metotları |
| Kullanıcı tanımlı değer tipleri | struct | Henüz yok (Project Valhalla) |
| Generics | Reified: tipler çalışma zamanında var | Erased: tipler derlemeden sonra silinir |
| Koleksiyon sorgulama | LINQ | Streams API |
| Async | async / await | Sanal thread'ler (Java 21), CompletableFuture |
| Checked exception'lar | Yok | Var |
| Operatör aşırı yükleme | Var | Yok |
| Null güvenliği | Nullable referans tipleri (C# 8) | Optional<T>, anotasyonlar |
| Başlıca kullanımlar | Unity oyunları, ASP.NET Core, Windows masaüstü, Azure | Kurumsal backend'ler, Android, büyük veri |
Sözdizimi: büyük ölçüde aynı
Sınıflar, metotlar, if, for, while, switch, try/catch neredeyse aynı okunur. Görünür farklar adlandırma kuralları ve birkaç anahtar kelimedir: C# metotları PascalCase (ToUpper, WriteLine), Java metotları camelCase (toUpperCase, println) yazılır; C# string ve bool yazar, Java String ve boolean; kalıtım C#'ta class Dog : Animal, Java'da class Dog extends Animal şeklindedir.
// Java
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> names = new ArrayList<>();
names.add("Ana");
names.add("Ben");
for (String n : names) {
System.out.println(n.toUpperCase());
}
}
}
Çıktı:
ANA
BEN
C# ayrıca string'leri == ile değere göre karşılaştırır; bu, Java'nın klasik başlangıç hatalarından birini ortadan kaldırır: Java'da iki String nesnesinde == referansları karşılaştırır, bu yüzden çalışma zamanında oluşturulan (girdiden okunan, birleştirilen) iki eşit string eşit değilmiş gibi görünebilir.
Getter ve setter yerine property'ler
Java sınıfları durumlarını genellikle bir IDE ya da Lombok tarafından üretilen getName() ve setName() metotlarıyla dışa açar. C#'ta property'ler vardır: alan gibi okunan ama kod çalıştıran üyeler.
// Java
public class Product {
private double price;
public double getPrice() { return price; }
public void setPrice(double price) {
if (price < 0) throw new IllegalArgumentException("negative");
this.price = price;
}
}
Çıktı:
Mug: 9.50
new Product { Name = ..., Price = ... } nesne başlatıcısı property'leri oluşturmadan hemen sonra ayarlar. Java record'ları (Java 16) değiştirilemez veri durumunu karşılar; C#'ta da record'lar (C# 9) ve geri kalan her şey için property'ler vardır.
Değer tipleri: struct'lar
Java'da kullanıcı tanımlı her tip, heap'te saklanan bir referans tipidir; yalnızca sekiz ilkel tip (int, double, ...) değerdir. C# struct ile kendi değer tiplerinizi tanımlamanıza izin verir. Bir struct atamada kopyalanır ve ayrı bir heap ayırması olmadan dizilerin ve diğer nesnelerin içinde satır içi yaşayabilir.
Çıktı:
a = (1, 2)
b = (99, 2)
1000
Bu, milyonlarca küçük nesnenin çöp toplayıcıya baskı yapacağı oyunlarda ve sayısal kodda önemlidir. Bkz. struct'lar.
Generics: reified ve erased
Java generic tip argümanlarını derleme sırasında siler: çalışma zamanında bir List<Integer> sadece bir List'tir ve List<int> yazılamaz (boxed Integer nesneleri alırsınız). C# tip argümanlarını çalışma zamanında tutar, bu yüzden List<int> ham int'leri saklar ve kod T'nin ne olduğunu sorabilir.
Çıktı:
3 items of type Int32
1 items of type String
List`1
typeof(T) ve new T() çalışır, çünkü çalışma zamanı T'yi bilir. Java'da ikisi de derleme hatasıdır ve olağan çözüm bir Class<T> nesnesini ortalıkta taşımaktır.
LINQ ve stream'ler
İki dilde de koleksiyonları filtrelemek ve dönüştürmek için akıcı bir API vardır. Java'nınki Streams API'dir (Java 8); C#'ınki LINQ'tur (C# 3), ayrıca bir sorgu sözdizimi vardır ve Entity Framework aracılığıyla veritabanlarına karşı çalışır.
// Java
List<String> expensive = products.stream()
.filter(p -> p.getPrice() > 20)
.sorted(Comparator.comparing(Product::getPrice))
.map(Product::getName)
.collect(Collectors.toList());
Çıktı:
Lamp, Chair
Total: 126
İşlemler bire bir eşleşir (filter Where, map Select, collect(toList()) ToList() olur) ve C# sürümlerinde stream() ya da collector gerekmez. new { Name = ..., Price = ... } nesneleri anonim tiplerdir; Java'da doğrudan karşılığı yoktur.
Async ve eşzamanlılık
C# 2012'de async/await'i getirdi: bir async metot bir Task döndürür ve await onu bir thread'i bloklamadan askıya alır. JavaScript, Python ve Rust daha sonra aynı anahtar kelimeleri benimsedi. Java farklı bir yol izledi: CompletableFuture zincirleri ve Java 21'den beri sıradan bloklayan kodu ucuz hale getiren sanal thread'ler.
// C#
async Task<string> LoadAsync(HttpClient http, string url)
{
string body = await http.GetStringAsync(url);
return body.Substring(0, 100);
}
// Java 21 with virtual threads: plain blocking code on a cheap thread
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
executor.submit(() -> client.send(request, BodyHandlers.ofString()));
}
İki yaklaşım da çok sayıda eşzamanlı isteğe ölçeklenir. C# asenkronluğu metot imzalarında görünür kılar; Java ise onu çalışma zamanında gizler.
İstisnalar, operatörler ve daha küçük farklar
- Checked exception'lar. Java bir metodu belirli istisnaları bildirmeye ya da yakalamaya zorlar (
throws IOException). C#'ta checked exception hiç yoktur. - Operatör aşırı yükleme. C# tiplerin
+,==,<ve benzerlerini tanımlamasına izin verir;decimalveDateTimearitmetiğinin doğal okunmasının nedeni budur. Java izin vermez (BigDecimal.add). - Varsayılan olarak virtual. Java metotları
finalişaretlenmedikçe override edilebilir; C# metotlarının override edilebilmesi içinvirtualişaretlenmesi gerekir ve override eden metotoverridedemelidir. - Extension metotlar. C# mevcut tiplere metot ekleyebilir (
"text".IsPalindrome()); Java ekleyemez. - Nullable değer tipleri. C#'ta
int?null olabilen bir int'tir; Java boxedIntegerkullanır. - İşaretsiz tipler. C#'ta
uint,ulong,ushortve işaretsiz birbytevardır; Java'nınbyte'ı işaretlidir ve 16 bitlikchardışında işaretsiz tamsayı tipi yoktur.
Ekosistem, iş imkânları ve hangisini öğrenmeli
Java'nın ekosistemi açık kaynak sunucu dünyasında daha büyüktür: Spring, Kafka, Spark, Hadoop, Elasticsearch ve çoğu Apache projesi Java'dır. Android uygulamaları Kotlin ya da Java ile yazılır. C#'ın yığını daha bütünleşiktir: dili, çalışma zamanını, web framework'ünü (ASP.NET Core), ORM'yi (Entity Framework) ve ana IDE'yi (Visual Studio) tek bir üretici sürdürür ve Unity onu oyun geliştirmenin merkezine koyar.
İki dilin de büyük bir iş piyasası vardır ve aralarındaki denge bölgeye ve sektöre bağlıdır. C#, Microsoft ve Azure üzerine kurulu şirketlerde, finans ve sağlık yazılımlarında ve oyun stüdyolarında güçlüdür.
Unity ile oyun yapmak, Windows masaüstü uygulamaları geliştirmek ya da bir .NET şirketinde çalışmak istiyorsanız C#'ı seçin. Android'i, büyük veriyi ya da backend'i JVM üzerinde olan bir şirketi hedefliyorsanız Java'yı seçin. Hangisi olursa olsun diğeri için gereken kavramları öğretir: sınıflar, interface'ler, generics, koleksiyonlar, istisnalar ve çöp toplayıcılı bir çalışma zamanı.
Sıkça Sorulan Sorular
C# Java'ya benziyor mu?
Evet, çok. İkisi de C tarzı sözdizimine sahip, statik tipli, nesne yönelimli, çöp toplayıcılı ve bir sanal makine için bytecode'a derlenen dillerdir. Bir Java geliştiricisi C#'ı ilk günden okuyabilir. Farklar ayrıntılardadır: C#'ta property'ler, kullanıcı tanımlı değer tipleri, reified generics, LINQ ve async/await vardır; Java'da ise checked exception'lar ve daha büyük bir açık kaynak sunucu ekosistemi vardır.
Önce C# mı öğrenmeliyim, Java mı?
Ne yapmak istediğinize göre seçin. Unity oyunları, Windows masaüstü uygulamaları ve Microsoft ile Azure üzerine kurulu şirketler için C#. Android (Kotlin ile birlikte), büyük kurumsal backend'ler ve Kafka ile Spark gibi büyük veri araçları için Java. Diller o kadar yakındır ki sonradan geçiş aylar değil haftalar sürer.
C# Java'dan daha mı hızlı?
Aynı performans sınıfındadırlar: ikisi de JIT ile yerel koda derlenir ve kuşak tabanlı çöp toplayıcılar kullanır. C#, struct'lar, Span<T> ve boxing olmadan değer tipleri üzerinde generics sayesinde daha fazla düşük seviye kontrol verir; bu, çok bellek ayıran kodda işe yarar. Tipik web yüklerinde framework ve veritabanı dilden çok daha önemlidir.
C#'ta Java'daki gibi checked exception var mı?
Hayır. C#'ta hiçbir istisna tipi bildirilmek ya da yakalanmak zorunda değildir; bir metot imzası ne fırlattığını listelemez. Tasarımcılar checked exception'ların boş catch bloklarına ve kırılgan imzalara yol açtığına karar verdi. Bunun yerine istisnaları /// <exception> XML yorumlarıyla belgelersiniz.
Hangisinde daha çok iş var, C# mı Java mı?
İkisinin de büyük bir iş piyasası vardır ve hangisinin daha çok ilanı olduğu ülkeye ve sektöre bağlıdır, bu yüzden çalışmak istediğiniz yerdeki ilanlara bakın. C#, Microsoft kullanan kurumsal şirketlerde, finansta, sağlıkta ve oyun stüdyolarında; Java büyük bankalarda, telekomda, e-ticaret backend'lerinde ve Android'de güçlüdür.