Java vs C++: Farklar ve Benzerlikler
C++ biliyorsan, Java'ya geçiş sana su gibi gelecek — söz dizimi çok benzer. Ama altta devasa farklar var. C++ bilmiyorsan da sorun yok — bu ders Java'nın tasarım kararlarını anlamana yardımcı olacak, çünkü Java'nın birçok özelliği C++'ın sorunlarına tepki olarak doğmuştur.
Java, C++'ın "güzel kısımlarını al, tehlikeli kısımlarını çıkar" felsefesiyle tasarlandı. James Gosling'in sözüyle: "C++ without the sharp edges" — keskin köşeleri olmayan C++.
Analoji: Otomobil vs Otomatik Araç
C++ bir yarış arabası gibidir. Vites, debriyaj, fren kuvveti — her şeyi sen kontrol edersin. Doğru kullanırsan inanılmaz performans alırsın, ama bir hata yaparsan duvar gelir.
Java bir otomatik araç gibidir. Vites otomatik, park sensörleri var, hız limiti aşılınca uyarı verir. Yarış arabasıyla aynı hızda gidemezsin belki, ama çok daha güvenli bir yolculuk yaparsın ve hedefe ulaşma olasılığın çok daha yüksek.
Her ikisi de seni istediğin yere götürür. Soru, yolculukta ne kadar kontrol istediğin ve ne kadar risk almak istediğin.
Hızlı Karşılaştırma Tablosu
| Özellik | C++ | Java |
|---|---|---|
| Platform | Platforma bağımlı | Platform bağımsız (JVM) |
| Derleme | Doğrudan makine koduna | Bytecode'a (JVM çalıştırır) |
| Bellek yönetimi | Manuel (new/delete) | Otomatik (Garbage Collector) |
| Pointer | Var (güçlü ama tehlikeli) | Yok (referanslar var) |
| Çoklu kalıtım | Var (sınıflardan) | Yok (interface ile çözülür) |
| Header dosyaları | Var (.h dosyaları) | Yok |
| Operator overloading | Var | Yok (String + hariç) |
| Destructor | Var | Yok (finalize deprecated) |
| Goto | Var | Yok |
| Struct | Var | Yok (class kullanılır) |
| Unsigned tipler | Var | Yok (Java 8+ kısmen) |
| Ön işlemci (#define) | Var | Yok |
| Standart kütüphane | STL | Java Collections Framework |
| Hız | Genellikle daha hızlı | JIT ile yaklaşıyor |
| Güvenlik | Daha riskli | Daha güvenli |
Bellek Yönetimi: En Büyük Fark
Bu, iki dil arasındaki en fundamental farktır.
C++: Manuel Bellek Yönetimi
// C++ kodu
#include <iostream>
using namespace std;
int main() {
// Bellek ayır
int* sayi = new int(42);
cout << *sayi << endl;
// Belleği serbest bırak — SEN yapmalısın
delete sayi;
// Bunu unutursan → memory leak!
// Bunu iki kez yaparsan → undefined behavior!
return 0;
}C++'ta new ile ayırdığın her belleği delete ile serbest bırakmalısın. Unutursan memory leak (bellek sızıntısı) olur. Program çalıştıkça gittikçe daha fazla bellek tüketir ve sonunda çöker.
Java: Otomatik Bellek Yönetimi
// Java kodu
public class BellekYonetimi {
public static void main(String[] args) {
// Bellek ayır
String mesaj = new String("Merhaba");
System.out.println(mesaj);
// Belleği serbest bırakmana gerek YOK
// Garbage Collector halleder
mesaj = null; // Referansı kaldır
// GC bir süre sonra "Merhaba" nesnesini temizler
}
}Java'da new ile nesne oluşturursun ama delete diye bir şey yok. Garbage Collector (GC) kullanılmayan nesneleri otomatik tespit edip temizler.
Bu karar Java'yı C++'tan çok daha güvenli ama biraz daha az kontrollü yapar. Büyük çoğunlukla bu trade-off işine yarar.
⚠️ Dikkat: Otomatik bellek yönetimi "bellek sorunlarını düşünme" demek değildir. Java'da da memory leak olabilir — örneğin, bir koleksiyona sürekli eleman ekleyip hiç çıkarmazsan. Ama C++ tarzı "delete'i unuttum" sorunları Java'da yok.
Pointer vs Referans
C++: Pointer'lar
C++'ta pointer, bir bellek adresini tutan değişkendir. Güçlü ama tehlikeli:
// C++ kodu
int x = 10;
int* ptr = &x; // ptr, x'in adresini tutar
cout << *ptr << endl; // 10 — dereferencing
cout << ptr << endl; // 0x7ffd5e8a — bellek adresi
// Pointer aritmetiği
int arr[] = {10, 20, 30};
int* p = arr;
cout << *(p + 1) << endl; // 20 — bir sonraki elemanı
// Tehlike: Dangling pointer
int* tehlikeli = new int(42);
delete tehlikeli;
cout << *tehlikeli << endl; // UNDEFINED BEHAVIOR!Pointer hataları C++'ın en büyük sorunudur:
Dangling pointer: Silinmiş belleğe erişim
Null pointer dereference: Null pointer'ı okuma
Buffer overflow: Array sınırını aşma
Memory leak: Belleği serbest bırakmayı unutma
Java: Referanslar
Java'da pointer yoktur. Bunun yerine referanslar var. Referanslar da aslında arka planda bellek adresleri tutar ama sen bu adresleri göremez, manipüle edemezsin:
// Java kodu
public class ReferansOrnegi {
public static void main(String[] args) {
String isim = new String("Ali");
// isim bir referanstır — "Ali" nesnesinin adresini tutar
// AMA bu adresi göremez, değiştiremezsin
String baska = isim;
// baska da aynı nesneyi referans eder
System.out.println(isim); // Ali
System.out.println(baska); // Ali
// Pointer aritmetiği YOK
// Bellek adresini YOK
// & ve * operatörleri YOK (bu anlamda)
}
}Java'nın referansları pointer'lardan daha kısıtlı ama çok daha güvenli. Dangling pointer, buffer overflow gibi sorunlar Java'da pratik olarak mümkün değil.
Platform Bağımlılık
C++: Platform Bağımlı
// C++ — Windows'ta derlersen Windows'ta çalışır
// Linux'ta çalıştırmak istersen Linux için tekrar derlemen gerek
g++ -o program program.cpp // Linux derlemesi
cl program.cpp // Windows derlemesi (MSVC)C++ kodu doğrudan makine koduna derlenir. Makine kodu işlemciye ve işletim sistemine özeldir. Windows'ta derlenen .exe dosyası Linux'ta çalışmaz.
Java: Platform Bağımsız
# Java — bir kere derle, her yerde çalıştır
javac Program.java # Bytecode oluşur (her yerde aynı)
java Program # Herhangi bir OS'ta çalışır (JVM varsa)Java kodu bytecode'a derlenir, bytecode JVM tarafından çalıştırılır. JVM her platforma özeldir ama bytecode evrenseldir.
Pratikte bu şu demek: Java ile yazdığın .jar dosyasını Windows'tan Linux'a, Mac'e, hatta Raspberry Pi'ye kopyalayıp çalıştırabilirsin. C++ ile bunu yapamazsın.
Çoklu Kalıtım
C++: Sınıflardan Çoklu Kalıtım
// C++ — birden fazla sınıftan kalıtım alabilirsin
class Hayvan {
public:
void yemekYe() { cout << "Yemek yiyor" << endl; }
};
class UcanVarlik {
public:
void uc() { cout << "Uçuyor" << endl; }
};
// İki sınıftan birden kalıtım
class Yarasa : public Hayvan, public UcanVarlik {
// yemekYe() ve uc() metodlarına sahip
};Ama çoklu kalıtımın ünlü bir sorunu var: Diamond Problem.
class A { public: void metod() { cout << "A" << endl; } };
class B : public A { };
class C : public A { };
class D : public B, public C {
// D.metod() → B'nin A'sı mı, C'nin A'sı mı?
// Belirsizlik! (virtual inheritance ile çözülür ama karmaşık)
};Java: Interface ile Çoklu Kalıtım
Java, diamond problem'den kaçınmak için sınıflardan çoklu kalıtıma izin vermez. Bunun yerine interface kullanır:
// Java — sınıftan tek kalıtım, interface'den çoklu
interface Yuzebilir {
void yuz();
}
interface Ucabilir {
void uc();
}
class Hayvan {
void yemekYe() {
System.out.println("Yemek yiyor");
}
}
// Tek sınıftan kalıtım + birden fazla interface
class Ordek extends Hayvan implements Yuzebilir, Ucabilir {
public void yuz() {
System.out.println("Yüzüyor");
}
public void uc() {
System.out.println("Uçuyor");
}
}Java 8'den itibaren interface'ler default metot içerebilir, bu da çoklu kalıtımın avantajlarını sağlar ama diamond problem'i kontrol altında tutar.
Header Dosyaları
C++: .h ve .cpp Ayrımı
C++'ta genellikle iki dosya olur:
// Hayvan.h — Declaration (bildiri)
#ifndef HAYVAN_H
#define HAYVAN_H
class Hayvan {
public:
void sesCikar();
int getYas();
private:
int yas;
};
#endif// Hayvan.cpp — Implementation (uygulama)
#include "Hayvan.h"
#include <iostream>
void Hayvan::sesCikar() {
std::cout << "..." << std::endl;
}
int Hayvan::getYas() {
return yas;
}Header dosyaları, include guard'lar (#ifndef), preprocessor direktifleri... C++'ın en zahmetli kısımlarından biri.
Java: Tek Dosya
Java'da header dosyası yok. Her şey tek dosyada:
// Hayvan.java — Hepsi burada
public class Hayvan {
private int yas;
public void sesCikar() {
System.out.println("...");
}
public int getYas() {
return yas;
}
}Java derleyicisi sınıflar arası bağımlılıkları otomatik çözer. #include yazmana gerek yok. Bir sınıfı kullanmak istiyorsan import edersin, o kadar.
Operator Overloading
C++: Operatör Aşırı Yükleme Var
// C++ — kendi tiplerinde + operatörünü tanımlayabilirsin
class Vektor {
public:
double x, y;
Vektor operator+(const Vektor& diger) {
return {x + diger.x, y + diger.y};
}
};
Vektor a = {1.0, 2.0};
Vektor b = {3.0, 4.0};
Vektor c = a + b; // operator+ çağrılırJava: Operator Overloading Yok
Java'da operatörleri yeniden tanımlayamazsın. Tek istisna: + operatörü String birleştirme için çalışır (ama sen bunu değiştiremezsin, dile gömülü).
// Java — operatör tanımlayamazsın, metot kullanırsın
public class Vektor {
double x, y;
Vektor topla(Vektor diger) {
Vektor sonuc = new Vektor();
sonuc.x = this.x + diger.x;
sonuc.y = this.y + diger.y;
return sonuc;
}
}
// Kullanım:
// Vektor c = a.topla(b); // a + b yerineNeden? Java tasarımcıları, operator overloading'in kodu okunaksız yapabileceğine karar verdi. a + b gördüğünde bunun gerçekten toplama mı, yoksa programcının tanımladığı bambaşka bir işlem mi olduğunu bilemezsin. Metot adı (topla()) niyeti daha net ifade eder.
Derleme Modeli
C++: Preprocessor → Compiler → Linker
kaynak.cpp → Preprocessor → Compiler → Object dosya (.o) → Linker → Çalışabilir dosya (.exe)C++'ta derleme süreci çok adımlı. Preprocessor (#include, #define işler), compiler (makine koduna çevirir), linker (obje dosyalarını birleştirir). Her adımda farklı hatalar çıkabilir.
Java: Compiler → JVM
Kaynak.java → javac → Bytecode (.class) → JVM → ÇalışmaJava'nın derleme süreci daha basit. Header dosyası yok, linker yok, preprocessor yok. javac direkt bytecode üretir, JVM çalıştırır.
Hata Yönetimi
C++: Exception + Hata Kodları
C++'ta hata yönetimi karışıktır — bazı kütüphaneler exception, bazıları hata kodu döndürür:
// C++ — karışık hata yönetimi
try {
int* ptr = new int[1000000000];
} catch (std::bad_alloc& e) {
cout << "Bellek yetersiz: " << e.what() << endl;
}
// Veya hata kodu:
FILE* f = fopen("dosya.txt", "r");
if (f == NULL) {
cout << "Dosya açılamadı" << endl;
}Java: Checked + Unchecked Exceptions
Java'da hata yönetimi daha sistematik:
// Java — zorunlu exception yönetimi
try {
FileReader dosya = new FileReader("dosya.txt");
// Dosya işlemleri...
} catch (FileNotFoundException e) {
System.out.println("Dosya bulunamadı: " + e.getMessage());
} finally {
System.out.println("Bu blok her durumda çalışır");
}Java'nın checked exception sistemi, bazı hataları yakalamayı zorunlu kılar. Derleyici "bu metod FileNotFoundException fırlatabilir, ya yakala ya da bildir" der. C++'ta böyle bir zorunluluk yok.
Ortak Söz Dizimi
İki dilin söz dizimi çok benzer. C++ bilen biri Java kodunu rahatlıkla okuyabilir:
// Java — C++ bilene tanıdık gelecek
public class Benzerlikler {
public static void main(String[] args) {
// Değişken tanımlama — aynı
int x = 10;
double y = 3.14;
char c = 'A';
// if-else — aynı
if (x > 5) {
System.out.println("Büyük");
} else {
System.out.println("Küçük");
}
// for döngüsü — aynı
for (int i = 0; i < 5; i++) {
System.out.println(i);
}
// while döngüsü — aynı
int sayac = 0;
while (sayac < 3) {
System.out.println(sayac);
sayac++;
}
// switch — aynı
switch (x) {
case 1:
System.out.println("Bir");
break;
case 10:
System.out.println("On");
break;
default:
System.out.println("Diğer");
}
}
}Kontrol yapıları (if, for, while, switch), operatörler (+, -, *, /, %, ==, !=), ve genel söz dizimi neredeyse aynı. C++ bilen biri Java'ya çok hızlı adapte olur.
String Karşılaştırması
Bu önemli bir fark. Dikkat et:
C++
string a = "Merhaba";
string b = "Merhaba";
if (a == b) { // İçerik karşılaştırır ✓
cout << "Eşit!" << endl;
}Java
String a = "Merhaba";
String b = new String("Merhaba");
if (a == b) { // Referans karşılaştırır — FALSE olabilir! ✗
System.out.println("Eşit");
}
if (a.equals(b)) { // İçerik karşılaştırır — TRUE ✓
System.out.println("Eşit");
}Java'da == operatörü referansları (adresleri) karşılaştırır, içerikleri değil. String içeriğini karşılaştırmak için .equals() kullan. Bu, yeni başlayanların en sık yaptığı hatalardan biridir.
💡 İpucu: Java'da String karşılaştırmasında her zaman .equals() kullan. == sadece primitive tipler (int, double, boolean vb.) için güvenlidir.
Detaylı Karşılaştırma: Belirli Konular
Array Tanımlama
// C++
int arr[5] = {1, 2, 3, 4, 5}; // Stack'te, sabit boyut
int* arr2 = new int[5]; // Heap'te, delete[] gerekir// Java
int[] arr = {1, 2, 3, 4, 5}; // Her zaman heap'te
int[] arr2 = new int[5]; // delete gerek yok, GC halleder
System.out.println(arr.length); // 5 — length özelliği varJava'da array'ler her zaman heap'te oluşturulur ve length özelliğine sahiptir. C++'ta array boyutunu kendin takip etmelisin.
Main Fonksiyonu
// C++
int main() {
return 0;
}
// veya
int main(int argc, char* argv[]) {
return 0;
}// Java
public static void main(String[] args) {
// return yok (void)
}C++'ta main bağımsız bir fonksiyondur ve int döndürür. Java'da main bir sınıfın statik metodu ve void'dir.
Konsol Çıktısı
// C++
#include <iostream>
using namespace std;
cout << "Merhaba" << " " << "Dünya" << endl;
printf("Sayı: %d\n", 42);// Java
System.out.println("Merhaba " + "Dünya");
System.out.printf("Sayı: %d%n", 42);Ne Zaman Hangisi?
Her iki dilin de güçlü olduğu alanlar var:
C++ Tercih Et:
Sistem programlama: İşletim sistemi, sürücü (driver) geliştirme
Oyun motorları: Unreal Engine, Unity'nin alt katmanı
Gömülü sistemler: Mikrodenetleyiciler, gerçek zamanlı sistemler
Yüksek performans gereken işler: HFT (High-Frequency Trading), bilimsel simülasyonlar
Donanıma yakın işler: Doğrudan bellek kontrolü gereken yerler
Java Tercih Et:
Kurumsal uygulamalar: Bankalar, sigorta, e-ticaret
Web servisleri: REST API, mikroservisler
Android uygulamaları: Mobil uygulama geliştirme
Büyük veri: Hadoop, Spark, Kafka
Büyük takım projeleri: Java'nın güvenlik mekanizmaları büyük ekiplerde daha az bug demek
C++'tan Java'ya Geçiş Rehberi
C++ biliyorsan, Java'ya geçerken unutman gerekenler:
`delete` ve `free` unut — GC halleder
Pointer unut — Referanslar kullan
Header dosyaları unut —
importyeterli`#include`, `#define` unut — Preprocessor yok
Operator overloading unut — Metot yaz
`struct` unut — Her şey
classGlobal fonksiyon unut — Her metot bir sınıfın içinde
Destructor unut — GC ve try-with-resources kullan
Ve hatırlaman gerekenler:
`equals()` kullan — String karşılaştırmasında
==kullanmaHer şey sınıf içinde — Java'da sınıfsız kod yok
`boolean` yaz — C++'taki
booldeğil`System.out.println` yaz — C++'taki
coutyerineException handling öğren — Checked exception zorunlu
Özet
Java, C++'ın söz dizimini alıp tehlikeli özellikleri çıkarmış bir dildir: pointer yok, manuel bellek yönetimi yok, çoklu sınıf kalıtımı yok.
Bellek yönetimi en büyük fark: C++'ta manuel (new/delete), Java'da otomatik (Garbage Collector).
Java platform bağımsız (bytecode + JVM), C++ platforma bağımlı (doğrudan makine kodu).
Java'da header dosyası yok, operator overloading yok, preprocessor yok — daha basit bir derleme modeli.
String karşılaştırmasında Java'da
==yerine.equals()kullanılır — en sık yapılan hata budur.C++ performans ve kontrol istenen yerlerde, Java güvenlik ve üretkenlik istenen yerlerde tercih edilir.
AI Asistan
Sorularını yanıtlamaya hazır