GitHub JDK Intellij Idea Community Git Java Tutorials
git init
git add .
git commit -m "add message"
git push -u origin master
git clone https://github.com/hamitmizrak/ibb_ecodation_javacore.git
Class isimleri PascalCase göre yazılır
Class isimleri: Fiil olarak kullanmayız (mak-mek)
Class : Java 1 tane public class vardır (inner class hariç)
Class : Java static class yoktur (inner class hariç)
Paket isimleri: Küçük harflerle yazılır.
Paket isimleri: fiil olarak kullanmayız (mak-mek)
Paket kısa net bir şekilde olması gerekiyor.
Javada Her biten kelime ; ile bitirmek zorundayız.
Java case sensitive bir dildir. (Küçük büyük harfe duyarlı yüksek seviyede bir dildir.)
Maven, Java projelerini oluşturmak, yönetmek ve otomatikleştirmek için kullanılan bir build automation (inşa otomasyonu) aracıdır. Apache tarafından geliştirilmiştir ve özellikle Java projelerinde bağımlılık yönetimi, derleme, test etme ve dağıtım süreçlerini kolaylaştırır. Maven, XML tabanlı bir yapılandırma dosyası olan pom.xml
kullanarak projenin yapılandırmasını ve bağımlılıklarını yönetir.
Maven’in Sağladıkları:
- Bağımlılık Yönetimi: Projeye eklenmesi gereken kütüphaneleri otomatik olarak indirir.
- Proje Yapılandırması: Projeyi standart bir yapıda düzenler.
- Otomatik Derleme: Projeyi derler (
mvn compile
). - Test Çalıştırma: JUnit ve TestNG gibi test araçlarıyla testleri çalıştırır (
mvn test
). - Paketleme: Projeyi
jar
veyawar
formatında paketler (mvn package
). - Dağıtım Yönetimi: Uygulamayı uzak sunuculara veya depolara gönderir (
mvn deploy
).
pom.xml
(Project Object Model) dosyası, Maven projelerinin merkezi yapılandırma dosyasıdır. Projenin bağımlılıklarını, sürüm bilgilerini, eklentilerini ve yapılandırmalarını içerir.
Örnek bir pom.xml
dosyası:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.7.4</version>
</dependency>
</dependencies>
</project>
Bu dosya:
- Projenin kimliğini (
groupId
,artifactId
,version
) - Bağımlılıklarını (
dependencies
) - Yapılandırmalarını içerir.
JDK (Java Development Kit), Java ile uygulama geliştirmek için kullanılan geliştirme ortamıdır. İçerisinde:
- JRE (Java Runtime Environment) (Çalışma zamanı ortamı)
- JVM (Java Virtual Machine) (Java Sanal Makinesi)
- Java Compiler (javac) (Java derleyicisi)
- Java Debugger (jdb) (Hata ayıklayıcı)
- Java API ve kütüphaneleri bulunur.
JRE (Java Runtime Environment), Java uygulamalarını çalıştırmak için gereken ortamdır. İçerisinde:
- JVM (Java Virtual Machine) bulunur.
- Java Kütüphaneleri içerir.
- Çalışma zamanı dosyaları bulunur.
Eğer sadece Java programlarını çalıştırmak istiyorsanız, JDK yerine sadece JRE yükleyebilirsiniz. Ancak, JRE Java kodu yazmak veya derlemek için yeterli değildir.
JVM (Java Virtual Machine), Java programlarını çalıştıran sanal bir makinedir. JVM sayesinde Java platform bağımsızdır çünkü Java kodu her işletim sisteminde çalışabilecek bayt koduna (.class
dosyalarına) çevrilir.
JVM’in Görevleri:
- Bayt kodunu çalıştırır.
- Bellek yönetimini yapar (Garbage Collection).
- Çoklu iş parçacığını (multithreading) destekler.
- Platform bağımsızlığı sağlar.
Compiler (Derleyici), insan tarafından yazılan yüksek seviyeli programlama dillerini makine koduna veya bayt koduna dönüştüren bir programdır. Java’da derleyici javac
olarak adlandırılır.
Java'da Çalışma Süreci:
- Java kodu yazılır:
MyClass.java
- Derleyici (
javac
) çalıştırılır:javac MyClass.java
- Bayt kodu (
.class
dosyası) oluşturulur:MyClass.class
- JVM bayt kodunu çalıştırır.
Interpreter (Yorumlayıcı), programın satır satır çalıştırılmasını sağlayan bir programdır. Java’da JVM içerisinde yer alan yorumlayıcı (interpreter), bayt kodlarını satır satır çalıştırır.
Derleyici (Compiler) vs. Yorumlayıcı (Interpreter):
- Derleyici: Tüm kodu derleyerek tek seferde çalıştırılabilir hale getirir.
- Yorumlayıcı: Kodu satır satır çalıştırır.
Java, nesne yönelimli (OOP), platform bağımsız, güvenli, çok iş parçacıklı (multithreading) ve taşınabilir bir programlama dilidir.
- 1995’te Sun Microsystems tarafından geliştirildi.
- "Bir kere yaz, her yerde çalıştır" (Write Once, Run Anywhere - WORA) prensibiyle çalışır.
- Mobil, web, masaüstü ve büyük ölçekli sistemlerde kullanılır.
- Platform Bağımsızdır. (JVM sayesinde her yerde çalışır)
- Nesne Yönelimli Programlama (OOP) Desteği vardır.
- Güvenlidir. (Bellek yönetimi ve güvenlik mekanizmaları içerir)
- Çok İş Parçacıklı (Multithreading) çalışmayı destekler.
- Otomatik Bellek Yönetimi (Garbage Collection) yapar.
- Dağıtık ve Ağ Tabanlı Uygulamaları Destekler.
Java'da değişkenlerin alabileceği veri türlerini ifade eder. İki ana kategoriye ayrılır:
- Primitive Types (İlkel Veri Tipleri)
- Reference Types (Referans Tipleri)
Java'daki ilkel veri tipleri (Primitive Types) hafızada doğrudan değer saklayan basit veri türleridir.
Veri Tipi | Boyut | Varsayılan Değer | Aralık |
---|---|---|---|
byte |
1B | 0 | -128 to 127 |
short |
2B | 0 | -32,768 to 32,767 |
int |
4B | 0 | -2^31 to 2^31-1 |
long |
8B | 0L | -2^63 to 2^63-1 |
float |
4B | 0.0f | ~7 basamak |
double |
8B | 0.0d | ~15 basamak |
char |
2B | '\u0000' | Unicode karakterler |
boolean |
1B | false |
true veya false |
Wrapper Class’lar, primitive veri tiplerinin nesne olarak kullanılmasını sağlar.
Örneğin:
int num = 10;
Integer obj = Integer.valueOf(num);
Primitive -> Wrapper Dönüşümleri:
int -> Integer
double -> Double
char -> Character
boolean -> Boolean
Wrapper class’lar Java Collections API’lerinde kullanılır çünkü koleksiyonlar yalnızca nesne saklayabilir.
javac
(Java Compiler) ve bayt kodu (bytecode) süreci, derleme süresi ve oluşturulan .class
dosyasının boyutunu etkileyebilir. Aşağıda bunun nasıl gerçekleştiğine dair detaylı bir açıklama bulabilirsiniz.
-
Kodun Karmaşıklığı:
- Daha fazla sınıf, metod ve kod satırı içeren projeler daha uzun sürede derlenir.
- Büyük projelerde, bağımlılıklar ve
import
edilen kütüphaneler derleme süresini uzatabilir.
-
Optimize Edilmiş Derleme (
javac
Seçenekleri):- Incremental Compilation (Artımlı Derleme):
- Eğer sadece değişiklik yapılan sınıflar derlenirse,
javac
süresi kısalır.
- Eğer sadece değişiklik yapılan sınıflar derlenirse,
- Hata Ayıklama Seçenekleri (
-g:none
):javac -g:none
komutu hata ayıklama bilgilerini içermeyen bir bytecode oluşturur ve derleme süresini kısaltabilir.
- Çoklu İş Parçacığı (Multithreading) Kullanımı:
- Büyük projelerde Gradle gibi derleme sistemleri çoklu iş parçacığı desteği sağlar, böylece derleme süresi azalır.
- Incremental Compilation (Artımlı Derleme):
-
Donanım ve JVM Yapılandırması:
- Daha hızlı CPU ve SSD kullanan sistemlerde derleme süresi düşer.
- Yetersiz RAM veya düşük işlem gücü derleme süresini artırır.
Bytecode, javac
tarafından üretilen platformdan bağımsız bir ara koddur ve .class
dosyalarında saklanır.
-
Kodun İçeriği ve Karmaşıklığı:
- Uzun metotlar, fazla satır kod ve daha fazla
class
tanımlaması dosya boyutunu artırır.
- Uzun metotlar, fazla satır kod ve daha fazla
-
Yerel Değişkenler ve Sabit Havuzu (Constant Pool):
- Java’nın String Constant Pool ve diğer sabit değişkenleri yönetme mekanizması, fazla sayıda string veya sabit tanımı içeren kodlarda
.class
dosyasının boyutunu artırabilir.
- Java’nın String Constant Pool ve diğer sabit değişkenleri yönetme mekanizması, fazla sayıda string veya sabit tanımı içeren kodlarda
-
Kullanılan Optimizasyonlar:
- JVM Optimizasyonları:
- JVM, bayt kodunu çalıştırırken Just-In-Time (JIT) Compiler gibi tekniklerle optimizasyon yapar.
- Inline Kod Kullanımı:
final
vestatic
değişkenlerin derleme zamanında yerine konulması, bytecode boyutunu artırabilir.
- JVM Optimizasyonları:
-
Lombok, Annotation Processing ve Kütüphaneler:
- Lombok, Spring gibi kütüphaneler otomatik kod üretme (code generation) yapıyorsa,
.class
dosya boyutunu artırabilir. - Annotation Processing, derleme zamanında ek kodlar üreterek dosya boyutunu büyütebilir.
- Lombok, Spring gibi kütüphaneler otomatik kod üretme (code generation) yapıyorsa,
-
Obfuscation (Kod Gizleme) ve Minifikasyon:
- Eğer kod ProGuard veya R8 gibi optimizasyon araçlarıyla küçültülürse, bytecode dosya boyutu azalır.
- Android projelerinde R8 ve ProGuard kullanımı, bytecode boyutunu küçültmek için yaygın bir tekniktir.
Aşağıdaki iki kodu karşılaştıralım:
public class SimpleClass {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
- Derleme Süresi: Çok kısa (~milisaniyeler)
- Bytecode Boyutu: Küçük (~1-2 KB)
import java.util.ArrayList;
public class ComplexClass {
public static void main(String[] args) {
ArrayList<Integer> numbers = new ArrayList<>();
for (int i = 0; i < 100000; i++) {
numbers.add(i);
}
System.out.println(numbers.size());
}
}
- Derleme Süresi: Daha uzun (~milisaniyeler ile saniyeler arasında)
- Bytecode Boyutu: Daha büyük (~10-20 KB)
- Kodun karmaşıklığı ve kullanılan yapılar hem derleme süresini hem de bayt kodunun boyutunu etkiler.
- Optimize edilmiş derleme (
javac -g:none
, ProGuard gibi araçlar) bytecode boyutunu azaltabilir. - Büyük projelerde derleme süresi donanıma ve çoklu iş parçacığı desteğine bağlı olarak değişebilir.
- Fazla sayıda sınıf, uzun metotlar ve büyük sabit havuzu derleme süresini ve bytecode boyutunu artırır.
Özet: Daha fazla kod satırı, büyük sınıflar, fazladan kütüphane kullanımı ve karmaşık yapıların kullanımı hem derleme süresini uzatır hem de .class
dosyalarının boyutunu artırır.
Java'da değişken isimlendirme kuralları sözdizimsel (syntax) kurallar ve en iyi uygulamalar (best practices) olarak ikiye ayrılır. Sözdizim kurallarına uyulmazsa derleme hatası alınır, en iyi uygulamalara uyulmaması ise okunabilirliği ve bakımı zorlaştırır.
Java'da değişken isimlendirme aşağıdaki zorunlu kurallara tabidir:
- Alfabede yer alan harfler (
a-z
,A-Z
) kullanılabilir. - Rakamlar (
0-9
) kullanılabilir, ancak değişken ismi rakamla başlayamaz. - Alt çizgi
_
ve dolar işareti$
kullanılabilir. - Java anahtar kelimeleri (reserved words) değişken adı olarak kullanılamaz.
Örneğin,int
,class
,static
,for
,if
gibi kelimeler değişken adı olamaz.
Geçersiz Değişken | Hata Nedeni |
---|---|
1number |
Rakamla başlayamaz |
int |
Java anahtar kelimesidir |
first-name |
- işareti kullanılamaz |
@value |
@ özel karakteri kullanılamaz |
my variable |
Boşluk içeremez |
Geçerli değişken adları derleme hatası vermez, ancak bazı yazım standartlarına uyulması okunabilirliği artırır. En iyi uygulamalar şunlardır:
Java'da değişkenler için camelCase kullanılır:
- İlk kelime küçük harfle başlar, sonraki kelimeler büyük harfle başlar.
Örnek:
int studentAge;
double accountBalance;
String firstName;
boolean isActive;
- Kısa ve anlamsız değişken adlarından kaçının.
- Değişkenin ne yaptığını veya hangi veriyi sakladığını anlatan isimler kullanın.
❌ Kötü Örnek:
int x;
double y;
✅ İyi Örnek:
int studentCount;
double totalSalary;
- Java'da değişkenler küçük harfle başlar, ardından gelen kelimeler büyük harfle devam eder.
❌ Kötü Örnek:
int StudentCount;
✅ İyi Örnek:
int studentCount;
final
değişkenler büyük harf ve alt çizgi (_
) ile yazılmalıdır.
✅ İyi Örnek (Sabitler için):
final double PI = 3.14159;
final int MAX_USERS = 100;
Değişken isimlerinde boşluk (space) veya özel karakterler (@
, #
, !
, -
, %
) kullanılamaz.
❌ Geçersiz:
int my variable;
String first-name;
✅ Geçerli:
int myVariable;
String firstName;
_
ve$
kullanılabilir, ancak genellikle değişken isimlerinde kullanılmaz.- Özel durumlar:
_
genellikle sabit değerlerde (final static
) kullanılır.$
genellikle otomatik üretilen kodlarda kullanılır (örneğin, Java'nın iç mekanizmalarında).
✅ Geçerli:
String _privateVar; // Genellikle kaçınılır
String $generatedCode; // Kullanılabilir ama önerilmez
Kural | Örnek (✅ Doğru) | Örnek (❌ Yanlış) |
---|---|---|
Harf, rakam, _ , $ kullanılabilir |
age , userName , account_balance |
user-name , 1stName , my var |
Rakamla başlayamaz | name1 |
1name |
Anahtar kelimeler kullanılamaz | totalAmount |
class , int |
Camel case kullanılmalı | studentCount |
Studentcount , student_count |
Sabit değişkenler büyük harfle yazılmalı | MAX_USERS , PI |
MaxUsers , piValue |
Boşluk içeremez | fullName |
full name |
public class NamingExample {
public static void main(String[] args) {
int studentCount = 25;
double accountBalance = 1050.75;
final double PI = 3.14159;
boolean isAvailable = true;
System.out.println("Student Count: " + studentCount);
System.out.println("Account Balance: $" + accountBalance);
System.out.println("PI: " + PI);
System.out.println("Available: " + isAvailable);
}
}
- Java değişken isimlendirme kurallarına uymak kodun okunabilirliğini, bakımını ve standartlarını artırır.
- Camel Case kullanımı önerilir:
myVariable
- Sabitler (
final
) büyük harfle yazılır:MAX_VALUE
- Değişken isimleri anlamlı olmalı:
userName
,totalAmount
- Java anahtar kelimeleri değişken adı olarak kullanılamaz.
Bu kurallara uymak, kodunuzu daha anlaşılır, düzenli ve sürdürülebilir hale getirecektir. 🚀
Java'da Primitive Types (İlkel Veri Tipleri), temel ve hafif veri tipleridir. Java'nın hafıza yönetimi, hızlı işlem yapabilme ve düşük bellek tüketimi sağlaması için kullanılırlar. Primitive türler, doğrudan bellekte saklanır ve nesne (Object
) değildirler.
Java’da 8 adet primitive type vardır:
- Tam sayı tipleri:
byte
,short
,int
,long
- Ondalıklı sayılar:
float
,double
- Karakter tipi:
char
- Mantıksal tip:
boolean
-
Nesne Değildir:
- Primitive değişkenler doğrudan bellekte saklanır.
Integer
,Double
gibi Wrapper Class’lar nesne iken,int
,double
gibi primitive türler nesne değildir.
-
Daha Verimlidir:
- Nesne yerine doğrudan hafızada saklandıkları için işlemler daha hızlı gerçekleştirilir.
- Örneğin,
int
yerineInteger
kullanılırsa heap bellekte fazladan bir nesne oluşur.
-
Varsayılan Değerleri Vardır:
- Primitive değişkenler başlangıç değerleriyle başlar (örneğin
int
için0
,boolean
içinfalse
).
- Primitive değişkenler başlangıç değerleriyle başlar (örneğin
-
Değer Tutarlar, Referans Değil:
- Primitive türler değer bazlıdır, yani doğrudan değişkenin içinde tutulur.
int x = 10;
yazıldığında,x
değişkeninin içinde10
değeri saklanır.
Aşağıda Java'nın 8 primitive veri tipi detaylı bir şekilde açıklanmaktadır.
Bu veri tipleri ondalıklı olmayan sayıları saklamak için kullanılır.
Tip | Boyut | Aralık | Varsayılan Değer |
---|---|---|---|
byte |
1 byte | -128 to 127 | 0 |
short |
2 byte | -32,768 to 32,767 | 0 |
int |
4 byte | -2³¹ to (2³¹-1) | 0 |
long |
8 byte | -2⁶³ to (2⁶³-1) | 0L |
- Bellek tasarrufu sağlamak için kullanılır.
- Sık kullanılan küçük değerler için uygundur.
- Örneğin 100 kişilik öğrenci listesi tutarken kullanışlıdır.
byte smallNumber = 100;
byte minByte = -128;
byte maxByte = 127;
byte
'tan büyük,int
'ten küçük değerler için kullanılır.- Bellek kullanımını optimize etmek için uygundur.
short shortNumber = 32000;
short minShort = -32768;
short maxShort = 32767;
- Java'da en çok kullanılan tam sayı tipidir.
- Varsayılan olarak tamsayı değerleri
int
türündedir.
int myAge = 25;
int totalUsers = 500000;
int minInt = -2147483648;
int maxInt = 2147483647;
- Büyük sayılar için kullanılır.
- Sayının sonuna
L
harfi eklenmelidir (long number = 10000000000L;
).
long population = 7800000000L; // Dünya nüfusu
long distanceToSun = 149600000000L; // Güneşe olan mesafe (km)
Ondalıklı sayılar için kullanılan kayan nokta tipleridir.
Tip | Boyut | Yaklaşık Hassasiyet | Varsayılan Değer |
---|---|---|---|
float |
4 byte | ~7 basamak | 0.0f |
double |
8 byte | ~15 basamak | 0.0d |
- Daha az yer kaplar ama kesinlik kaybı olabilir.
- Sayının sonuna
f
eklenmelidir (float pi = 3.14f;
).
float pi = 3.14159f;
float gravity = 9.81f;
- Hassas matematiksel işlemler için kullanılır.
- Varsayılan ondalıklı veri tipidir.
double precisePi = 3.141592653589793;
double speedOfLight = 299792458.0;
- Tek bir karakter saklar.
- Unicode destekler, yani her dili ve sembolü içerebilir.
char letter = 'A';
char digit = '5';
char symbol = '@';
char smiley = '\u263A'; // ☺ Unicode karakter
- İki olası değer alır:
true
veyafalse
- Kontrol yapılarında (if, while, for) yaygın kullanılır.
boolean isJavaFun = true;
boolean isRaining = false;
Java'da bir primitive değişken başlangıç değeri atanmazsa, şu varsayılan değerleri alır:
Veri Tipi | Varsayılan Değer |
---|---|
byte |
0 |
short |
0 |
int |
0 |
long |
0L |
float |
0.0f |
double |
0.0d |
char |
'\u0000' (Boş karakter) |
boolean |
false |
Java, primitive türlerin nesne olarak kullanılmasını sağlayan Wrapper Class’ları içerir.
Primitive Type | Wrapper Class |
---|---|
byte |
Byte |
short |
Short |
int |
Integer |
long |
Long |
float |
Float |
double |
Double |
char |
Character |
boolean |
Boolean |
Örneğin:
int x = 10;
Integer y = Integer.valueOf(x); // Primitive -> Wrapper (Boxing)
int z = y.intValue(); // Wrapper -> Primitive (Unboxing)
Java'da primitive types (ilkel türler) ve wrapper types (sarmalayıcı türler) arasındaki farkları detaylı bir şekilde inceleyelim.
- Primitive Types: Java'daki en temel veri türleridir. Bellekte doğrudan değerleri saklarlar ve hafıza açısından daha verimli çalışırlar.
- Wrapper Types: Primitive türlerin nesne (object) olarak kullanılabilmesini sağlayan Java sınıflarıdır. Java'da koleksiyonlar (List, Set, Map gibi) nesnelerle çalıştığından, primitive türlerin nesne versiyonları (wrapper types) kullanılır.
Özellik | Primitive Types | Wrapper Types |
---|---|---|
Tanım | Doğrudan değeri saklayan türlerdir. | Primitive türleri sarmalayan sınıflardır. |
Hafıza Kullanımı | Daha az bellek kullanır, daha verimlidir. | Daha fazla bellek tüketir (ekstra nesne oluşturur). |
Depolama | Stack bellekte saklanır. | Heap bellekte saklanır (Nesne olarak oluşturulduğu için). |
Değer Tipi | Değer (value) tipindedir. | Referans (object) tipindedir. |
Null Olabilir mi? | Hayır (null olamaz). | Evet (null olabilir). |
Varsayılan Değer | int → 0, double → 0.0, boolean → false vb. | null (eğer nesne oluşturulmamışsa). |
Nesne Davranışı | Nesne değildir, direkt hesaplama yapar. | Nesnedir, metodları vardır. |
Koleksiyonlarda Kullanım | Doğrudan kullanılamaz (List gibi bir şey yazamayız). | Kullanılabilir (List mümkündür). |
Dönüştürme İşlemi | Boxing & Unboxing gerektirir. | Boxing & Unboxing ile primitive türlere dönüşebilir. |
Primitive Type | Wrapper Class |
---|---|
byte |
Byte |
short |
Short |
int |
Integer |
long |
Long |
float |
Float |
double |
Double |
char |
Character |
boolean |
Boolean |
public class PrimitiveExample {
public static void main(String[] args) {
int x = 10;
double y = 20.5;
boolean isJavaFun = true;
System.out.println("x: " + x);
System.out.println("y: " + y);
System.out.println("Java eğlenceli mi? " + isJavaFun);
}
}
📌 Burada x
, y
ve isJavaFun
değişkenleri doğrudan bellekte saklanır, nesne oluşturulmaz.
public class WrapperExample {
public static void main(String[] args) {
Integer x = Integer.valueOf(10);
Double y = Double.valueOf(20.5);
Boolean isJavaFun = Boolean.TRUE; // veya new Boolean(true) (Eski kullanım)
System.out.println("x: " + x);
System.out.println("y: " + y);
System.out.println("Java eğlenceli mi? " + isJavaFun);
}
}
📌 Burada x
, y
ve isJavaFun
nesne olarak saklanır, heap bellekte yer kaplar.
Java 5 ile gelen Autoboxing ve Unboxing, primitive ve wrapper türleri arasında otomatik dönüşüm yapılmasını sağlar.
Primitive türler, otomatik olarak wrapper nesnelere dönüşür.
public class AutoboxingExample {
public static void main(String[] args) {
int primitiveValue = 100;
Integer wrapperValue = primitiveValue; // Autoboxing
System.out.println("Wrapper Integer: " + wrapperValue);
}
}
Bu kod, Integer wrapperValue = Integer.valueOf(primitiveValue);
ile aynıdır.
Wrapper türler, otomatik olarak primitive değerlere dönüşür.
public class UnboxingExample {
public static void main(String[] args) {
Integer wrapperValue = 200;
int primitiveValue = wrapperValue; // Unboxing
System.out.println("Primitive int: " + primitiveValue);
}
}
Bu kod, int primitiveValue = wrapperValue.intValue();
ile aynıdır.
Senaryo | Primitive Kullanımı | Wrapper Kullanımı |
---|---|---|
Hız & Performans Önemli | ✅ Daha hızlı | ❌ Yavaş |
Bellek Verimliliği | ✅ Az bellek kullanır | ❌ Fazla bellek harcar |
Koleksiyonlarda Kullanım (List, Set, Map) | ❌ Kullanılamaz | ✅ Kullanılabilir |
Null Değer Atama | ❌ Mümkün değil | ✅ Mümkün |
Nesne Yönelimli Programlama Gerekirse | ❌ Uygun değil | ✅ Nesne olarak kullanılabilir |
Metodlarla Çalışma | ❌ Metod içermez | ✅ Integer.parseInt() , Double.valueOf() gibi metodlar kullanılabilir |
- Performans kritikse ve koleksiyonlarla çalışılmıyorsa → Primitive types kullanılmalı.
- Koleksiyonlar (List, Map, Set) veya nesne yönelimli bir yapı gerekiyorsa → Wrapper types kullanılmalı.
- Null değerler gerekliliği varsa → Wrapper types tercih edilmeli.
- Hesaplamalar yapılıyorsa → Primitive types daha hızlı ve verimli çalışır.
Konu | Primitive Type | Wrapper Type |
---|---|---|
Hafıza Kullanımı | Az bellek harcar | Daha fazla bellek tüketir |
Hız | Daha hızlıdır | Daha yavaştır |
Null Olabilir mi? | ❌ Hayır | ✅ Evet |
Nesne mi? | ❌ Hayır | ✅ Evet |
Koleksiyonlarda Kullanılabilir mi? | ❌ Hayır | ✅ Evet |
📌 Özetle, performans gereken durumlarda primitive types kullanılır, nesne yönelimli işlemler ve koleksiyonlar için wrapper types gereklidir.
💡 Soru: List<int> list = new ArrayList<>();
neden hatalıdır?
📌 Çünkü primitive types koleksiyonlarda kullanılamaz. List<Integer> list = new ArrayList<>();
şeklinde wrapper type kullanmalıyız.
Bu detaylı açıklamalar, primitive ve wrapper türleri arasındaki farkları net bir şekilde anlamanıza yardımcı olacaktır! 🚀
- Primitive türler doğrudan bellekte saklanır, nesne değildir.
- Daha hızlıdır ve daha az bellek tüketir.
- 8 temel tür vardır:
byte
,short
,int
,long
,float
,double
,char
,boolean
. - Matematik işlemleri ve kontrollerde en verimli yöntemleri sunar.
Primitive türler Java'nın temelini oluşturur ve performans açısından büyük avantaj sağlar! 🚀
Eğer wrapper sınıflarını new
anahtar kelimesiyle oluşturmak istiyorsak, her bir primitive türünün wrapper sınıfını kullanarak aşağıdaki gibi yazabiliriz:
public class WrapperExample {
public static void main(String[] args) {
Byte wrapperTypeByte = new Byte((byte) 127);
wrapperTypeByte = null; // Wrapper sınıflar null alabilir
System.out.println(wrapperTypeByte);
Short wrapperTypeShort = new Short((short) 32767);
Integer wrapperTypeInt = new Integer(2147483647);
Long wrapperTypeLong = new Long(9223372036854775807L);
Float wrapperTypeFloat = new Float(14.23f);
Double wrapperTypeDouble = new Double(14.23);
Boolean wrapperTypeBoolean = new Boolean(true);
Character wrapperTypeChar = new Character('a');
System.out.println("Short: " + wrapperTypeShort);
System.out.println("Integer: " + wrapperTypeInt);
System.out.println("Long: " + wrapperTypeLong);
System.out.println("Float: " + wrapperTypeFloat);
System.out.println("Double: " + wrapperTypeDouble);
System.out.println("Boolean: " + wrapperTypeBoolean);
System.out.println("Character: " + wrapperTypeChar);
}
}
-
Java 9 ve Sonrasında
new
Kullanımı Önerilmez- Java 9'dan itibaren
new Byte()
,new Integer()
gibi kullanımlar depreceated (kullanım dışı) olarak işaretlenmiştir. - Bunun yerine doğrudan atama yapılmalıdır:
Byte wrapperTypeByte = 127; // Önerilen kullanım
- Çünkü: Java autoboxing mekanizması sayesinde
new
kullanmadan da bu türleri otomatik olarak wrapper class'lara çevirebilir.
- Java 9'dan itibaren
-
Performans ve Bellek Yönetimi
new
kullanımı gereksiz nesne oluşturduğu için heap belleği gereksiz yere doldurur.- Örneğin:
Integer a = 100; // Autoboxing (Önerilen kullanım) Integer b = new Integer(100); // Heap bellekte yeni nesne oluşturur
new Integer(100)
kullanırsanız heap’te yeni bir nesne oluşturulur ve gereksiz hafıza tüketilir.
- Eğer eski sürümlerle çalışmıyorsanız ve özel bir nedeniniz yoksa,
new
kullanmadan autoboxing yöntemini tercih etmelisiniz. - Java 9+ ile çalışıyorsanız,
new
kullanmaktan kaçının ve doğrudan atamaları kullanın. 🚀
Java'da primitive veri tipleri (int, double, boolean, char, float, long, short, byte) ve wrapper sınıfları (Integer, Double, Boolean, Character, Float, Long, Short, Byte) bellek yönetimi açısından farklı yerlerde saklanır. Bu iki veri tipi arasındaki en büyük fark, stack ve heap bellek yönetimi ile ilgilidir. Şimdi bu farkları çok detaylı şekilde inceleyelim.
Java bellek yönetiminde iki temel bölge vardır:
- Stack (Yığın Hafıza): Küçük, hızlı ve yönetimi kolaydır. Primitive veri tipleri burada saklanır.
- Heap (Yığın Hafıza): Daha büyük, daha yavaş ama esnek bir yapıya sahiptir. Wrapper sınıfları (nesne olarak kullanılan veriler) burada saklanır.
Özellik | Stack (Yığın Hafıza) | Heap (Yığın Hafıza) |
---|---|---|
Saklanan Veri Tipleri | Primitive değişkenler (int, double, char ) |
Nesneler ve Wrapper sınıfları (Integer, Double, Character ) |
Bellek Yönetimi | LIFO (Last In First Out – Son giren, ilk çıkar) | Garbage Collector tarafından yönetilir |
Hız | Çok hızlı | Görece daha yavaş |
Erişim Süresi | Stack değişkenlerine erişim daha hızlıdır | Heap değişkenlerine erişim daha yavaştır |
Ömür | Bir metodun çalışma süresi boyunca var olur | Program çalıştığı sürece var olabilir |
Bellek Alanı | Küçüktür | Daha büyüktür |
Çoklu Thread Kullanımı | Thread'e özeldir (Her thread'in kendi stack’i vardır) | Heap bellek tüm thread’ler tarafından paylaşılır |
Otomatik Temizleme | Otomatik temizlenir, Garbage Collector çalışmasına gerek yoktur | Garbage Collector tarafından yönetilir, bellek temizliği gerektiğinde yapılır |
Primitive veri tipleri hafızada doğrudan değer olarak saklanır. Örneğin:
int x = 10;
x
değişkeni stack hafızada saklanır.- Stack, değişkenleri hızlı bir şekilde yönetir ve fonksiyon bittiğinde otomatik olarak temizler.
Stack'teki bellek organizasyonu şu şekildedir:
Stack Memory:
+----------------------+
| int x = 10 |
+----------------------+
Eğer primitive yerine bir wrapper class (nesne) kullanırsak:
Integer y = new Integer(10);
Bu durumda, bellek yapısı şu şekilde olur:
y
değişkeni stack içinde bir referans olarak saklanır.new Integer(10)
ifadesiyle oluşturulan nesne heap hafızada saklanır.- Heap’te saklanan nesneye erişmek için stack’te bir referans (adres) tutulur.
Stack Memory:
+----------------------+
| Integer y (ref: 0xA) |
+----------------------+
Heap Memory:
+----------------------+
| [Integer: 10] (0xA) |
+----------------------+
Yani, primitive bir değişken doğrudan değeri içerirken, wrapper class'lar referansları saklar ve asıl veri heap içinde tutulur.
Şimdi stack ve heap farkını anlamak için aşağıdaki kodu inceleyelim:
public class MemoryTest {
public static void main(String[] args) {
int a = 5;
Integer b = new Integer(5);
modify(a, b);
System.out.println("a: " + a); // 5
System.out.println("b: " + b); // 5
}
public static void modify(int x, Integer y) {
x = 10; // Stack içindeki x değişir
y = new Integer(10); // Yeni bir nesne oluşturulur (Heap)
}
}
int a = 5;
→ Stack'te doğrudan 5 değeri saklanır.Integer b = new Integer(5);
→ Heap’te yeni bir Integer nesnesi oluşturulur. Stack'te referansı tutulur.modify(a, b);
metoduna çağrılırken:x
→ yeni bir stack değişkeni olarak 5 değerini kopyalar (pass by value).y
→ referans olarak yeni bir Integer nesnesi alır.
x = 10;
→ Stack içinde yeni bir değişken yaratılır ve değer değiştirilir.y = new Integer(10);
→ Heap’te yeni bir Integer nesnesi oluşturulur, ancak bumodify
metodu içinde kalır ve main metodundakib
değişkenini etkilemez.main
metodu bittiğinde,a
hâlâ5
,b
hâlâ5
olarak kalır.
Bu durum, primitive’lerin değiştirilememesi (pass-by-value) ve wrapper nesnelerinin yeni bir nesne oluşturduğunda eski referanslarını kaybetmesi nedeniyle oluşur.
Java, primitive ve wrapper sınıfları arasında otomatik dönüşüm sağlar. Buna Autoboxing ve Unboxing denir.
int primitiveValue = 100;
Integer wrapperValue = primitiveValue; // Autoboxing
- Burada
primitiveValue
, otomatik olarakInteger
nesnesine dönüştürülür ve heap’te saklanır.
Integer wrapperValue = 200;
int primitiveValue = wrapperValue; // Unboxing
wrapperValue
, heap’ten alınıp stack’te saklananprimitiveValue
değişkenine atanır.
Bu dönüşümler bazı performans kayıplarına neden olabilir, çünkü primitive tiplerde heap erişimi olmadığı için daha hızlı işlem yapılır.
Kullanım Durumu | Primitive Kullan (Stack) | Wrapper Kullan (Heap) |
---|---|---|
Hafıza Verimliliği | ✅ | ❌ (Heap daha fazla bellek kullanır) |
Performans (Hızlı Erişim) | ✅ | ❌ (Heap erişimi daha yavaş) |
Nesne Odaklı Programlama (OOP) | ❌ | ✅ (Nesne özellikleri ile kullanılabilir) |
Nullable Değerler (Null Atama) | ❌ | ✅ (Primitive null olamaz, wrapper olabilir) |
Collection (List, Set, Map) | ❌ | ✅ (Primitive veri tipleri Collection ile kullanılamaz) |
Eğer hafıza ve hız önemliyse, primitive tipleri kullanmalıyız.
Eğer nesne tabanlı programlama, null değeri saklama veya koleksiyonlar (List, Set, Map) ile çalışma gerekiyorsa, wrapper sınıfları kullanmalıyız.
- Primitive değişkenler stack hafızada tutulur, doğrudan değeri içerir ve daha hızlıdır.
- Wrapper sınıfları heap hafızada saklanır, referans üzerinden erişilir ve daha fazla bellek kullanır.
- Otomatik Boxing/Unboxing sayesinde dönüşümler mümkündür, ancak performansa dikkat edilmelidir.
Bu bilgiler doğrultusunda, projenin gereksinimlerine göre en uygun bellek kullanım stratejisini belirlemek gerekir. 🚀
Short wrapperTypeShort = new Short((short) 32767);
bununla Short wrapperTypeShort 2=32767 arasındaki far nedir ?
Java'da aşağıdaki iki satır arasındaki farkı inceleyelim:
Short wrapperTypeShort1 = new Short((short) 32767); // 1. Yöntem (Explicit Object Creation - new kullanımı)
Short wrapperTypeShort2 = 32767; // 2. Yöntem (Autoboxing)
Bu iki yaklaşımın arasındaki temel farklar şunlardır:
Short wrapperTypeShort1 = new Short((short) 32767);
new
anahtar kelimesi kullanıldığı için her çağrıldığında yeni bir nesne oluşturulur.- Heap bellekte ayrı bir nesne yaratılır.
- Garbage Collector (GC) tarafından temizlenmesi gerekir.
- Bellek tüketimi ve performans açısından dezavantajlıdır.
==
operatörü ile karşılaştırıldığında farklı nesneler olduğu için false dönebilir.- Java 9 ve sonraki sürümlerde bu yöntem depreceated (kullanım dışı) hale gelmiştir.
Short wrapperTypeShort2 = 32767;
- Autoboxing sayesinde primitive
short
değeri otomatik olarakShort
nesnesine dönüştürülür. - Java'nın Integer ve Short için cache mekanizmasını kullanır.
- Küçük sayı aralıklarında (
-128
ile127
arasında) önbellekten (cache) alınan nesneleri kullanabilir. - Daha performanslıdır, çünkü her seferinde yeni bir nesne oluşturmaz.
Aşağıdaki kodu çalıştırarak farkı gözlemleyebiliriz:
public class ShortComparison {
public static void main(String[] args) {
Short wrapperTypeShort1 = new Short((short) 127);
Short wrapperTypeShort2 = 127; // Autoboxing
Short wrapperTypeShort3 = new Short((short) 127);
Short wrapperTypeShort4 = 127; // Autoboxing
System.out.println(wrapperTypeShort1 == wrapperTypeShort3); // false (Heap'te farklı nesneler)
System.out.println(wrapperTypeShort2 == wrapperTypeShort4); // true (Cache mekanizması sayesinde aynı nesne)
Short wrapperTypeShort5 = 32767;
Short wrapperTypeShort6 = 32767;
System.out.println(wrapperTypeShort5 == wrapperTypeShort6); // false (Çünkü cache dışında)
}
}
- Eğer
new
kullanırsanız, heap bellekte yeni bir nesne oluşur ve==
operatörü farklı nesneler döndürdüğü içinfalse
olur. - Eğer
Short wrapperTypeShort2 = 32767;
şeklinde yazarsanız, Java autoboxing kullanır. - Java
-128
ile127
arasındaki değerleri cache olarak tuttuğu için bu aralıkta==
karşılaştırması true dönebilir. Ancak32767
gibi büyük değerler cache dışında olduğu için farklı nesneler oluşturulur.
✔ Performans açısından Short wrapperTypeShort = 32767;
(Autoboxing) tercih edilmelidir.
❌ new Short((short) 32767)
kullanımı gereksiz bellek tüketimine neden olur ve önerilmez.
Bu yüzden new
ile nesne oluşturmaktan kaçınılmalı ve autoboxing kullanımı tercih edilmelidir. 🚀
Java programlarının çalışma süreci hem compiler (derleyici) hem de interpreter (yorumlayıcı) içerir, ancak önce compiler çalışır, sonra interpreter devreye girer.
-
Compiler (Derleyici) İlk Çalışır:
- Java kaynak kodu (
.java
dosyaları) Javac (Java Compiler) tarafından Bytecode’a (.class
dosyaları) dönüştürülür. - Bytecode işletim sistemine bağımsızdır, yani her ortamda çalışabilir.
- Java kaynak kodu (
-
Interpreter (Yorumlayıcı) Sonra Çalışır:
- Java Virtual Machine (JVM), Bytecode’u alır ve Just-In-Time (JIT) Compiler ile çalıştırılabilir makine koduna dönüştürür.
- JVM, Bytecode'u satır satır yorumlar ve çalıştırır.
Java'daki bir programın baştan sona yaşam döngüsünü adım adım açıklayalım:
Geliştirici, Java kaynak kodunu (.java
dosyalarını) yazar.
Örneğin:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
Java compiler (javac
), kaynak kodunu Bytecode’a çevirir.
- Syntax kontrolü yapılır: Derleyici (
javac
), kodun sözdizimi hatalarını kontrol eder. - Optimizasyon yapılır: Kod en verimli hale getirilir.
- Bytecode üretilir: Makineye bağımsız
.class
dosyası oluşturulur.
javac HelloWorld.java
Bu komut sonucunda, aşağıdaki dosya oluşur:
HelloWorld.class
Bu .class
dosyası Java Bytecode içerir.
Java ClassLoader, .class
dosyalarını JVM’ye yükler.
- Bootstrap ClassLoader: Java’nın temel sınıflarını (
java.lang.*
) yükler. - Extensions ClassLoader: Ekstra kütüphaneleri (
lib/ext
dizinindekileri) yükler. - Application ClassLoader: Kullanıcının kendi yazdığı sınıfları yükler.
- JVM, Bytecode’un güvenliğini kontrol eder.
- Hatalı veya zararlı kodların çalışmasını önler.
- Bellek aşımı veya yasadışı bellek erişimlerini engeller.
- Java Interpreter, Bytecode’u satır satır okur ve çalıştırır.
- Ancak, sürekli yorumlama yavaş olabilir, bu yüzden JIT (Just-In-Time) Compiler devreye girer.
- JIT Compiler, tekrar eden kodları alır ve doğrudan makine koduna çevirir.
- JVM’nin performansını artırır, çünkü aynı kodun sürekli yorumlanmasını önler.
- Garbage Collector (GC): Kullanılmayan nesneleri bellekten temizler.
- Thread Management: Çoklu işlemler arasında zamanlamayı yönetir.
- Exception Handling: Çalışma sırasında oluşan hataları yakalar.
Eğer her şey doğru giderse, programın çıktısı ekrana yazdırılır:
Hello, World!
- Source Code (
.java
) yazılır. - Java Compiler (
javac
) kodu Bytecode (.class
) haline getirir. - ClassLoader,
.class
dosyasını JVM’ye yükler. - Bytecode Verification aşaması güvenlik kontrolü yapar.
- Interpreter, Bytecode’u satır satır yorumlar ve çalıştırır.
- JIT Compiler, sık kullanılan kodları makine koduna çevirir (performans artırır).
- Garbage Collector, kullanılmayan bellekleri temizler.
- Program sonucu ekrana yazdırılır.
✅ Önce Compiler (javac
) çalışır → Sonra Interpreter (JVM
) çalışır.
🚀 Sonuç: Java hem compiled (derlenen) hem de interpreted (yorumlanan) bir dildir.
Java'da Wrapper Type, primitive type (ilkel veri türleri) ile çalışırken nesneye (Object) ihtiyaç duyduğumuz durumlarda kullanılan sarmalayıcı (wrapper) sınıflardır.
Java’daki primitive veri türleri (int
, double
, boolean
vb.) nesne değildir. Ancak, Java’da birçok yapı (Koleksiyonlar List
, Set
, Map
vb.) nesnelerle çalışır. Bu nedenle primitive türleri nesnelere dönüştürmek için Wrapper Type kullanılır.
Örnek:
int x = 10; // Primitive type
Integer y = 10; // Wrapper type (Nesne)
Burada:
x
bir primitive int türüdür.y
ise Integer sınıfından bir nesnedir.
Primitive Type | Karşılık Gelen Wrapper Type |
---|---|
byte |
Byte |
short |
Short |
int |
Integer |
long |
Long |
float |
Float |
double |
Double |
char |
Character |
boolean |
Boolean |
💡 Wrapper sınıflar, primitive türlerin büyük harfle başlayan ve nesne olarak kullanılabilen versiyonlarıdır.
Wrapper sınıfları genellikle koleksiyonlarla çalışma, null değer atama, veri türleri arasında dönüşüm yapma gibi işlemler için kullanılır.
import java.util.ArrayList;
import java.util.List;
public class WrapperExample {
public static void main(String[] args) {
List<Integer> sayilar = new ArrayList<>();
sayilar.add(10); // int → Integer (Autoboxing)
sayilar.add(20);
System.out.println(sayilar); // [10, 20]
}
}
📌 List kullanılamaz! Java Koleksiyonları nesnelerle çalıştığından, List kullanmalıyız.
Java 5 ile gelen Autoboxing ve Unboxing, primitive türler ile Wrapper türler arasında otomatik dönüşüm sağlar.
Java, primitive türleri otomatik olarak nesneye çevirir.
public class AutoboxingExample {
public static void main(String[] args) {
int primitiveValue = 100;
Integer wrapperValue = primitiveValue; // Autoboxing (int → Integer)
System.out.println(wrapperValue); // 100
}
}
Arka planda şuna dönüşür:
Integer wrapperValue = Integer.valueOf(primitiveValue);
Wrapper türleri, otomatik olarak primitive türlerine dönüştürülür.
public class UnboxingExample {
public static void main(String[] args) {
Integer wrapperValue = 200;
int primitiveValue = wrapperValue; // Unboxing (Integer → int)
System.out.println(primitiveValue); // 200
}
}
Arka planda şuna dönüşür:
int primitiveValue = wrapperValue.intValue();
Wrapper sınıfları, primitive türlerde olmayan bazı metotlara sahiptir.
Integer intObj = Integer.valueOf(10);
Double doubleObj = Double.valueOf(5.5);
Boolean boolObj = Boolean.valueOf(true);
System.out.println(intObj); // 10
System.out.println(doubleObj); // 5.5
System.out.println(boolObj); // true
Integer intObj = Integer.valueOf(100);
int primitiveInt = intObj.intValue(); // Wrapper → Primitive
Double doubleObj = Double.valueOf(55.5);
double primitiveDouble = doubleObj.doubleValue(); // Wrapper → Primitive
System.out.println(primitiveInt); // 100
System.out.println(primitiveDouble); // 55.5
int sayi = Integer.parseInt("123");
double ondalik = Double.parseDouble("12.34");
boolean dogruMu = Boolean.parseBoolean("true");
System.out.println(sayi); // 123
System.out.println(ondalik); // 12.34
System.out.println(dogruMu); // true
📌 Eğer String geçersizse NumberFormatException
hatası alınır!
int sayi = 456;
String str = Integer.toString(sayi);
System.out.println(str); // "456"
Aynı işlem String.valueOf()
ile de yapılabilir:
String str2 = String.valueOf(sayi);
System.out.println(str2); // "456"
Senaryo | Primitive Kullanımı | Wrapper Kullanımı |
---|---|---|
Performans & Bellek | ✅ Daha hızlı, az bellek kullanır. | ❌ Daha fazla bellek kullanır. |
Koleksiyonlarla Kullanım | ❌ Kullanılamaz. (List<int> hata verir) |
✅ Kullanılabilir. (List<Integer> ) |
Null Değer Atama | ❌ Mümkün değil. | ✅ Mümkün (Integer x = null; ) |
Metot Kullanımı | ❌ Metotları yoktur. | ✅ valueOf() , parseInt() gibi metotlar içerir. |
Generics (Jenerik Türler) | ❌ Kullanılamaz (T extends int olmaz). |
✅ Kullanılabilir (T extends Number ). |
- Performans ve bellek önemliyse →
primitive type
kullanın. - Koleksiyonlar ve nesne yönelimli programlama gerekiyorsa →
wrapper type
kullanın. - Null değeri gerekliyse →
wrapper type
kullanın. - Matematiksel hesaplamalar için →
primitive type
daha hızlıdır.
Özellik | Primitive Type | Wrapper Type |
---|---|---|
Bellek Kullanımı | Az bellek tüketir. | Daha fazla bellek tüketir. |
Hız | Daha hızlıdır. | Daha yavaştır. |
Null Değer | ❌ Null olamaz. | ✅ Null olabilir. |
Nesne mi? | ❌ Hayır. | ✅ Evet. |
Metotları Var mı? | ❌ Hayır. | ✅ parseInt() , valueOf() gibi metotları vardır. |
Koleksiyonlarla Kullanılabilir mi? | ❌ Hayır. | ✅ Evet. |
📌 Özetle: Wrapper Type, nesne yönelimli programlama ve koleksiyonlarla çalışırken kullanılır. Ancak, performans ve bellek yönetimi açısından primitive type daha avantajlıdır.
💡 Soru: List<int> list = new ArrayList<>();
neden hata verir?
📌 Cevap: Java koleksiyonları nesne tutar. int
bir nesne değildir, bu yüzden List<Integer>
kullanmalıyız. 🚀
Java'da matematiksel işlemleri gerçekleştirmek için kullanılan Math sınıfı (java.lang.Math
), birçok hazır matematik fonksiyonu sunar. Bu fonksiyonlar sayesinde üstel, logaritmik, trigonometrik ve yuvarlama işlemleri gibi birçok işlemi gerçekleştirebiliriz.
✅ Math sınıfı java.lang
paketinin bir parçasıdır
✅ Statik metotlar içerir, bu yüzden nesne oluşturmaya gerek yoktur
✅ Performans açısından optimize edilmiştir
✅ Temel aritmetik, yuvarlama, üstel işlemler, trigonometri fonksiyonları içerir
Örneğin:
double sqrtValue = Math.sqrt(25); // 5.0
double powerValue = Math.pow(2, 3); // 8.0
double randomValue = Math.random(); // 0 ile 1 arasında rastgele sayı
Math sınıfı mutlak değer, maksimum, minimum gibi işlemleri kolayca yapar.
Metot | Açıklama | Örnek Kullanım |
---|---|---|
Math.abs(x) |
x’in mutlak değerini döndürür. | Math.abs(-10) → 10 |
Math.max(a, b) |
a ve b’nin maksimumunu bulur. | Math.max(5, 8) → 8 |
Math.min(a, b) |
a ve b’nin minimumunu bulur. | Math.min(5, 8) → 5 |
System.out.println(Math.abs(-15)); // 15
System.out.println(Math.max(100, 200)); // 200
System.out.println(Math.min(50, 30)); // 30
Metot | Açıklama | Örnek Kullanım |
---|---|---|
Math.sqrt(x) |
x’in karekökünü döndürür. | Math.sqrt(9) → 3.0 |
Math.pow(x, y) |
x’in y. kuvvetini hesaplar. | Math.pow(2, 3) → 8.0 |
Math.exp(x) |
e^x hesaplar. | Math.exp(2) → 7.389 |
Math.log(x) |
x’in doğal logaritmasını hesaplar (ln x). | Math.log(2.718) |
Math.log10(x) |
x’in 10 tabanında logaritmasını hesaplar. | Math.log10(100) → 2.0 |
System.out.println(Math.sqrt(16)); // 4.0
System.out.println(Math.pow(2, 5)); // 32.0
System.out.println(Math.exp(1)); // 2.718
System.out.println(Math.log(Math.E)); // 1.0
System.out.println(Math.log10(1000)); // 3.0
Java Math sınıfı yuvarlama işlemleri için farklı fonksiyonlar sunar.
Metot | Açıklama | Örnek Kullanım |
---|---|---|
Math.round(x) |
En yakın tam sayıya yuvarlar. | Math.round(5.7) → 6 |
Math.ceil(x) |
Yukarı yuvarlar. | Math.ceil(3.2) → 4.0 |
Math.floor(x) |
Aşağı yuvarlar. | Math.floor(3.9) → 3.0 |
System.out.println(Math.round(4.5)); // 5
System.out.println(Math.ceil(3.2)); // 4.0
System.out.println(Math.floor(6.8)); // 6.0
Trigonometri fonksiyonları radyan cinsinden hesaplama yapar.
Metot | Açıklama | Örnek Kullanım |
---|---|---|
Math.sin(x) |
x’in sinüsünü hesaplar. | Math.sin(Math.PI/2) → 1.0 |
Math.cos(x) |
x’in kosinüsünü hesaplar. | Math.cos(0) → 1.0 |
Math.tan(x) |
x’in tanjantını hesaplar. | Math.tan(Math.PI/4) → 1.0 |
Math.asin(x) |
x’in ters sinüsünü hesaplar. | Math.asin(0.5) |
Math.acos(x) |
x’in ters kosinüsünü hesaplar. | Math.acos(1) |
Math.atan(x) |
x’in ters tanjantını hesaplar. | Math.atan(1) |
System.out.println(Math.sin(Math.PI/2)); // 1.0
System.out.println(Math.cos(0)); // 1.0
System.out.println(Math.tan(Math.PI/4)); // 1.0
Math.random()
metodu 0.0 ile 1.0 arasında rastgele bir sayı döndürür.
Örnek Kullanımlar:
System.out.println(Math.random()); // 0.0 ile 1.0 arasında rastgele sayı
System.out.println((int)(Math.random() * 100)); // 0-99 arası sayı
System.out.println((int)(Math.random() * 50) + 1); // 1-50 arası sayı
Math sınıfı matematiksel sabitleri de içerir.
Sabit | Açıklama | Örnek Kullanım |
---|---|---|
Math.PI |
π değeri (3.141592653589793) | Math.PI * r * r (Daire Alanı) |
Math.E |
Euler sabiti (2.718281828459045) | Math.exp(1) → 2.718 |
System.out.println(Math.PI); // 3.141592653589793
System.out.println(Math.E); // 2.718281828459045
Aşağıdaki Java programı, Math sınıfının en önemli metodlarını içeren bir örnektir.
public class MathExample {
public static void main(String[] args) {
// Mutlak Değer
System.out.println("Mutlak Değer: " + Math.abs(-25));
// Karekök ve Üstel İşlemler
System.out.println("Karekök: " + Math.sqrt(64));
System.out.println("Üs Al: " + Math.pow(2, 5));
// Yuvarlama İşlemleri
System.out.println("Yuvarla (Round): " + Math.round(4.6));
System.out.println("Yukarı Yuvarla (Ceil): " + Math.ceil(4.2));
System.out.println("Aşağı Yuvarla (Floor): " + Math.floor(4.9));
// Rastgele Sayı
System.out.println("Rastgele Sayı (0-100): " + (int)(Math.random() * 100));
// Trigonometri
System.out.println("Sinüs: " + Math.sin(Math.toRadians(90)));
System.out.println("Kosinüs: " + Math.cos(Math.toRadians(0)));
// Matematiksel Sabitler
System.out.println("PI Sayısı: " + Math.PI);
}
}
- Java Math sınıfı, temel ve ileri matematik işlemlerini hızlı ve optimize bir şekilde yapar.
- Math metotları
static
olduğu için nesne oluşturmaya gerek yoktur. - Yuvarlama, üstel işlemler, logaritma, trigonometrik fonksiyonlar gibi birçok fonksiyon içerir.
🚀 Java'da matematik işlemleri için Math
sınıfını öğrenmek, sayısal işlemleri hızlı ve verimli yapmanızı sağlar! 🚀
Java'da escape sequences (kaçış dizileri), özel karakterleri String içinde kullanmamızı sağlayan ters eğik çizgi (\
) ile başlayan özel karakterlerdir. Normalde doğrudan yazılamayan karakterleri temsil ederler.
💡 Örneğin:
"
çift tırnak işareti bir String içinde doğrudan yazılamaz. ("Bu bir "örnek" metin"
) → Hatalı- Çözüm:
\"
kaçış dizisi kullanılır. ("Bu bir \"örnek\" metin"
) → Doğru
Kaçış Dizisi | Anlamı | Örnek Kullanımı |
---|---|---|
\n |
Yeni satır (Newline) | "Satır 1\nSatır 2" |
\t |
Sekme (Tab) | "İsim:\tMehmet" |
\' |
Tek tırnak (Single quote) | char c = '\''; |
\" |
Çift tırnak (Double quote) | "Bu bir \"örnek\" metin" |
\\ |
Ters eğik çizgi (Backslash) | "C:\\Users\\Documents" |
\r |
Satır başı (Carriage return) | "Merhaba\rDünya" |
\b |
Geri al (Backspace) | "ABC\bD" (Sonuç: "ABD") |
\f |
Form feed (Sayfa sonu) | "Sayfa sonu\fYeni Sayfa" |
\uXXXX |
Unicode karakteri | "\u00E7" (ç harfi) |
public class EscapeExample {
public static void main(String[] args) {
System.out.println("Merhaba Dünya!\nBu bir alt satıra geçti.");
}
}
Çıktı:
Merhaba Dünya!
Bu bir alt satıra geçti.
public class EscapeExample {
public static void main(String[] args) {
System.out.println("İsim:\tAhmet");
System.out.println("Soyisim:\tYılmaz");
}
}
Çıktı:
İsim: Ahmet
Soyisim: Yılmaz
public class EscapeExample {
public static void main(String[] args) {
System.out.println("Bu bir \"Java\" programıdır.");
System.out.println("Tek tırnak: \'A\' karakteri");
}
}
Çıktı:
Bu bir "Java" programıdır.
Tek tırnak: 'A' karakteri
public class EscapeExample {
public static void main(String[] args) {
System.out.println("Dosya yolu: C:\\Users\\Documents\\file.txt");
}
}
Çıktı:
Dosya yolu: C:\Users\Documents\file.txt
public class EscapeExample {
public static void main(String[] args) {
System.out.println("Merhaba\rDünya!");
}
}
Çıktı (bazı sistemlerde farklı olabilir):
Dünya!
📌 \r
, satır başına döner ve "Dünya!", "Merhaba"nın üzerine yazılır.
public class EscapeExample {
public static void main(String[] args) {
System.out.println("ABC\bD");
}
}
Çıktı:
ABD
📌 \b
ifadesi, son karakteri siler. "ABC\bD"
→ C
silinir, sonuç "ABD"
olur.
public class EscapeExample {
public static void main(String[] args) {
System.out.println("Sayfa sonu\fYeni Sayfa");
}
}
📌 Çoğu modern sistemde görünmezdir ama yazıcı ve eski terminallerde sayfa sonu karakteri olarak kullanılır.
public class EscapeExample {
public static void main(String[] args) {
System.out.println("Türkçe karakter: \u00E7, \u011F, \u015F");
}
}
Çıktı:
Türkçe karakter: ç, ğ, ş
📌 Unicode ile tüm dillerde özel karakterler kullanılabilir.
- Java'da kaçış dizileri, String içinde özel karakterleri kullanmamızı sağlar.
- En sık kullanılanlar:
\n
(yeni satır),\t
(sekme),\"
(çift tırnak),\\
(ters eğik çizgi). - Gelişmiş kullanım: Unicode (
\uXXXX
) ile özel karakterleri String içinde yazabiliriz.
📌 Özetle: Eğer bir metin içinde özel karakterler yazmak istiyorsanız, escape sequences kullanmanız gereklidir! 🚀
Scanner, Java’da kullanıcıdan giriş almak, dosyalardan veri okumak ve stringleri ayrıştırmak (parsing) için kullanılan bir sınıftır. java.util.Scanner paketinde bulunur.
Java’da veri girişlerini almak için System.in (klavyeden giriş), dosyalardan okuma (File), Stringlerden okuma gibi işlemler için kullanılır.
Kullanım Alanı | Açıklama |
---|---|
Kullanıcıdan veri almak | Scanner ile klavyeden giriş alabiliriz. |
Dosya okumak | Dosyalardan satır satır veya kelime kelime veri okuyabiliriz. |
String parçalama | String ifadeleri belirli bir ayraç ile bölebiliriz. |
Veri türlerine dönüştürme | String değerleri int , double , boolean gibi tiplere çevirebiliriz. |
Scanner sınıfı java.util paketinde bulunduğu için kullanmadan önce import edilmesi gerekir:
import java.util.Scanner;
💡 Eğer import java.util.Scanner;
yazmazsak, Java bu sınıfı tanımaz ve hata verir!
Scanner sınıfı ile farklı türlerde veri alabiliriz:
import java.util.Scanner;
public class ScannerExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Adınızı girin: ");
String ad = scanner.next(); // Tek kelime okur
System.out.print("Soyadınızı girin: ");
String soyad = scanner.next(); // Tek kelime okur
System.out.print("Cümlenizi girin: ");
scanner.nextLine(); // Önceki enter'ı temizler
String cumle = scanner.nextLine(); // Bütün satırı okur
System.out.println("Adınız: " + ad);
System.out.println("Soyadınız: " + soyad);
System.out.println("Girdiğiniz cümle: " + cumle);
scanner.close();
}
}
Metot | Açıklama |
---|---|
next() |
Tek bir kelime okur. Boşluk görünce okuma işlemi durur. |
nextLine() |
Bütün satırı okur. Enter tuşuna basılana kadar bekler. |
💡 Not: nextLine()
kullanmadan önce next()
veya nextInt()
gibi metotlar çalıştırılırsa, enter karakterini temizlemek için bir scanner.nextLine();
satırı eklenmelidir.
import java.util.Scanner;
public class ScannerExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Yaşınızı girin: ");
int yas = scanner.nextInt();
System.out.print("Boyunuzu girin: ");
double boy = scanner.nextDouble();
System.out.print("Ağırlığınızı girin: ");
float agirlik = scanner.nextFloat();
System.out.println("Yaşınız: " + yas);
System.out.println("Boyunuz: " + boy);
System.out.println("Kilonuz: " + agirlik);
scanner.close();
}
}
Metot | Aldığı Veri Türü |
---|---|
nextInt() |
int (Tamsayı) |
nextDouble() |
double (Ondalıklı sayı) |
nextFloat() |
float (Küçük ondalıklı sayı) |
nextLong() |
long (Büyük tamsayı) |
nextShort() |
short (Küçük tamsayı) |
nextByte() |
byte (Çok küçük tamsayı) |
nextBoolean() |
boolean (true/false) |
📌 Dikkat: Kullanıcı eğer yanlış türde giriş yaparsa (nextInt()
beklerken a
girerse), hata (InputMismatchException
) oluşur.
Scanner sınıfı sadece klavyeden giriş almak için değil, dosyalardan veri okumak için de kullanılır.
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FileScannerExample {
public static void main(String[] args) {
try {
File file = new File("veri.txt");
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
String satir = scanner.nextLine();
System.out.println(satir);
}
scanner.close();
} catch (FileNotFoundException e) {
System.out.println("Dosya bulunamadı!");
}
}
}
new File("veri.txt")
→"veri.txt"
dosyasını açar.hasNextLine()
→ Dosyada satır kaldığı sürece okumaya devam eder.nextLine()
→ Satır satır okur.- Dosya yoksa
FileNotFoundException
fırlatılır.
Scanner, virgül, boşluk veya özel karakterlere göre string parçalamak için kullanılabilir.
import java.util.Scanner;
public class ScannerDelimiterExample {
public static void main(String[] args) {
String veri = "Ahmet,Mehmet,Ayşe,Fatma";
Scanner scanner = new Scanner(veri);
scanner.useDelimiter(",");
while (scanner.hasNext()) {
System.out.println(scanner.next());
}
scanner.close();
}
}
Ahmet
Mehmet
Ayşe
Fatma
📌 Özet: scanner.useDelimiter(",")
ile virgülü ayırıcı olarak belirledik.
Scanner nesnesi kullanıldıktan sonra kapatılmalıdır, aksi halde kaynak sızıntısı olabilir.
scanner.close();
💡 Eğer Scanner kapatılmazsa, bellek sızıntısına neden olabilir!
Eğer kullanıcıdan sürekli giriş almak istiyorsak, bir döngü kullanabiliriz.
import java.util.Scanner;
public class ScannerLoopExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("Bir sayı girin (Çıkış için -1): ");
int sayi = scanner.nextInt();
if (sayi == -1) {
System.out.println("Çıkış yapıldı.");
break;
}
System.out.println("Girdiğiniz sayı: " + sayi);
}
scanner.close();
}
}
📌 Kullanıcı -1
girene kadar veri girişi yapabilir.
- Scanner, kullanıcıdan veri almak, dosya okumak, stringleri ayrıştırmak için kullanılır.
nextInt()
,nextDouble()
,nextLine()
,next()
gibi metotlarla farklı veri türleri okunabilir.- Dosyalardan veri okumak için
Scanner(File file)
kullanılabilir. - Belirli bir karaktere göre bölmek için
useDelimiter()
kullanılabilir. - Kaynak sızıntısını önlemek için
scanner.close();
ile kapatılmalıdır.
🚀 Scanner, Java'da veri almak için en yaygın kullanılan sınıflardan biridir!
Java'nın ünlü sloganı "Write Once, Run Anywhere" şeklindedir. "Everywhere" değil, "Anywhere" kullanılır.
✅ "Write Once, Run Anywhere" (WORA)
Bu slogan, Java programlarının bir kez yazıldığında farklı platformlarda çalışabileceğini ifade eder. Anywhere kelimesi, "herhangi bir yerde" anlamına gelir, yani farklı işletim sistemleri ve donanımlarda çalışabilir demektir.
❌ "Write Once, Run Everywhere"
"Everywhere" kelimesi "her yerde" anlamına gelir, ancak Java'nın çalışma prensibi tam olarak bu değildir. JVM'nin yüklü olmadığı bir ortamda Java çalışmaz, bu yüzden "everywhere" yerine "anywhere" daha doğru bir ifadedir.
💡 Mülakatta doğru cevap:
✅ "Write Once, Run Anywhere" söylemelisiniz.
❌ "Everywhere" derseniz teknik olarak yanlış olur.
Conditional (Koşullu) ifadeler, bir programın belirli koşullara bağlı olarak farklı yollar izlemesini sağlar. Mantıksal karşılaştırmalar ve şartlar kullanarak belirli blokların çalıştırılmasını kontrol ederiz.
Java'da kullanılan başlıca koşullu ifadeler şunlardır:
if
veif-else
ifadelerielse if
(çoklu koşullar)switch-case
yapısı- Ternary (
?:
) operatörü - Short-Circuit (
&&
ve||
) operatörleri
- Koşul doğru (
true
) olduğunda kod çalıştırılır. - Yanlış (
false
) olursa hiçbir şey yapılmaz.
Örnek 1: Basit if
kullanımı
public class IfExample {
public static void main(String[] args) {
int sayi = 10;
if (sayi > 5) { // Koşul doğru mu? Evet!
System.out.println("Sayı 5'ten büyüktür.");
}
}
}
Çıktı:
Sayı 5'ten büyüktür.
sayi > 5
olduğu içinif
bloğu çalıştı.
- Koşul
true
iseif
bloğu çalışır. - Koşul
false
olursaelse
bloğu çalışır.
Örnek 2: if-else
kullanımı
public class IfElseExample {
public static void main(String[] args) {
int sayi = 3;
if (sayi > 5) {
System.out.println("Sayı 5'ten büyüktür.");
} else {
System.out.println("Sayı 5'ten küçük veya eşittir.");
}
}
}
Çıktı:
Sayı 5'ten küçük veya eşittir.
sayi = 3
olduğu içinif
bloğu çalışmadı,else
bloğu çalıştı.
- Birden fazla koşulu test etmek için
else if
kullanılır. - İlk doğru (
true
) koşul çalıştırılır, diğerleri atlanır.
Örnek 3: else if
kullanımı
public class ElseIfExample {
public static void main(String[] args) {
int not = 75;
if (not >= 90) {
System.out.println("Harf Notu: A");
} else if (not >= 80) {
System.out.println("Harf Notu: B");
} else if (not >= 70) {
System.out.println("Harf Notu: C");
} else {
System.out.println("Harf Notu: F");
}
}
}
Çıktı:
Harf Notu: C
not = 75
, yaninot >= 70
olduğu için sadece "Harf Notu: C" yazdırıldı.
- Bir değişkenin belirli değerlere eşit olup olmadığını kontrol eder.
- Koşula bağlı olarak ilgili
case
çalıştırılır. - Eğer hiçbir
case
eşleşmezsedefault
bloğu çalışır. - Her case’den sonra
break
kullanılmazsa, aşağıdaki tüm case’ler çalışır.
public class SwitchExample {
public static void main(String[] args) {
int gun = 3;
switch (gun) {
case 1:
System.out.println("Pazartesi");
break;
case 2:
System.out.println("Salı");
break;
case 3:
System.out.println("Çarşamba");
break;
case 4:
System.out.println("Perşembe");
break;
default:
System.out.println("Geçersiz gün numarası");
}
}
}
Çıktı:
Çarşamba
gun = 3
olduğunda,case 3
çalıştı.
- Koşullu ifadeleri kısaltmak için kullanılır.
- Tek satırda
if-else
mantığı sağlar. - Kullanım:
(koşul) ? "true ise çalışır" : "false ise çalışır"
public class TernaryExample {
public static void main(String[] args) {
int sayi = 10;
String sonuc = (sayi > 5) ? "Büyük" : "Küçük veya eşit";
System.out.println(sonuc);
}
}
Çıktı:
Büyük
sayi > 5
olduğu için"Büyük"
değeri atanır.
Kısa devre (Short-Circuiting), gereksiz hesaplamaları önlemek için kullanılan bir optimizasyondur.
Operatör | Açıklama |
---|---|
&& (AND) |
Eğer ilk koşul false ise, ikinci koşula bakmaz. |
` |
public class ShortCircuitExample {
public static void main(String[] args) {
int a = 5;
int b = 10;
if (a > 10 && ++b > 15) { // `a > 10` zaten false, ikinci koşula bakmaz
System.out.println("Koşul sağlandı.");
}
System.out.println("b: " + b); // b artırılmadı!
}
}
Çıktı:
b: 10
a > 10
false olduğu için++b
çalışmaz,b
aynı kalır.
public class ShortCircuitExample2 {
public static void main(String[] args) {
int x = 5;
int y = 10;
if (x < 10 || ++y > 15) { // `x < 10` true, ikinci koşula bakılmaz!
System.out.println("Koşul sağlandı.");
}
System.out.println("y: " + y); // y artırılmadı!
}
}
Çıktı:
Koşul sağlandı.
y: 10
x < 10
true olduğu için++y
çalışmaz.
Yapı | Kullanım Amacı |
---|---|
if |
Belirli bir koşulu test etmek |
if-else |
Koşul yanlışsa alternatif blok çalıştırmak |
else if |
Birden fazla koşulu kontrol etmek |
switch-case |
Belirli değerleri eşleştirerek çalıştırmak |
?: (Ternary) |
Kısa if-else ifadeleri için |
&& , ` |
Bu koşullu yapılar, Java programlarında karar mekanizmaları oluşturmak için temel taşlardır. 🚀
Döngüler (Loops), bir işlemi tekrar tekrar belirli bir koşul sağlanana kadar çalıştırmak için kullanılır. Java'da en yaygın kullanılan döngüler şunlardır:
- for döngüsü
- while döngüsü
- do-while döngüsü
- for-each (enhanced for loop)
Bu döngülerle birlikte break
ve continue
gibi kontrol ifadeleri kullanılarak döngü akışı yönetilebilir.
for
döngüsü, tekrar sayısı bilinen işlemleri yapmak için kullanılır. Döngü çalıştırılmadan önce, koşul ve artış/azalış değerleri belirlenir.
Yapısı:
for (başlangıç_değeri; koşul; artırma/azaltma) {
// Döngü bloğu
}
public class ForLoopExample {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
System.out.println("i: " + i);
}
}
}
Çıktı:
i: 1
i: 2
i: 3
i: 4
i: 5
i = 1
olarak başlar.i <= 5
olduğu sürece çalışır.- Her iterasyonda
i++
ilei
artırılır.
public class EvenNumbers {
public static void main(String[] args) {
for (int i = 2; i <= 10; i += 2) {
System.out.println("Çift sayı: " + i);
}
}
}
Çıktı:
Çift sayı: 2
Çift sayı: 4
Çift sayı: 6
Çift sayı: 8
Çift sayı: 10
i = 2
olarak başlar.i <= 10
olduğu sürece çalışır.i += 2
ile her turdai
2 artırılır.
while
, koşul sağlandığı sürece çalışan bir döngüdür. Kaç kere çalışacağı önceden bilinmeyen durumlar için kullanılır.
Yapısı:
while (koşul) {
// Döngü bloğu
}
public class WhileLoopExample {
public static void main(String[] args) {
int i = 1;
while (i <= 5) {
System.out.println("i: " + i);
i++; // i artırılıyor, yoksa sonsuz döngü olur.
}
}
}
Çıktı:
i: 1
i: 2
i: 3
i: 4
i: 5
- İlk olarak
i = 1
. - Koşul
i <= 5
sağlandıkça çalışır. - Her iterasyonda
i++
artırılır.
import java.util.Scanner;
public class WhileUserInput {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int sayi;
System.out.println("5 girene kadar sayı girin:");
while (true) { // Sonsuz döngü
sayi = scanner.nextInt();
if (sayi == 5) {
System.out.println("Döngü sonlandı.");
break; // 5 girildiğinde döngü kırılır.
}
}
}
}
Örnek Giriş/Çıkış:
5 girene kadar sayı girin:
1
2
3
5
Döngü sonlandı.
- Kullanıcı 5 girene kadar veri girer.
- 5 girildiğinde
break;
ile döngü sona erer.
do-while
, önce döngü çalıştırılır, sonra koşul kontrol edilir. Koşul yanlış olsa bile en az bir kere çalışır.
Yapısı:
do {
// Döngü bloğu
} while (koşul);
import java.util.Scanner;
public class DoWhileExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int sifre;
do {
System.out.print("Şifreyi girin (1234): ");
sifre = scanner.nextInt();
} while (sifre != 1234);
System.out.println("Giriş başarılı!");
}
}
Örnek Giriş/Çıkış:
Şifreyi girin (1234): 1111
Şifreyi girin (1234): 2222
Şifreyi girin (1234): 1234
Giriş başarılı!
- Şifre doğru girilene kadar tekrar eder.
- En az bir kez çalışır, çünkü
do
bloğu önce çalışır.
for-each
, dizi ve koleksiyonları (Array, List, Set, vs.) daha kolay gezmek için kullanılır.
Yapısı:
for (VeriTipi eleman : Dizi/Koleksiyon) {
// Döngü bloğu
}
public class ForEachExample {
public static void main(String[] args) {
int[] sayilar = {10, 20, 30, 40, 50};
for (int sayi : sayilar) {
System.out.println("Sayı: " + sayi);
}
}
}
Çıktı:
Sayı: 10
Sayı: 20
Sayı: 30
Sayı: 40
Sayı: 50
for-each
,for
döngüsüne göre daha okunaklıdır.- Diziler, List'ler ve Set'ler üzerinde gezinmek için idealdir.
public class BreakExample {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
if (i == 5) {
break; // 5 olduğunda döngü sona erer.
}
System.out.println("i: " + i);
}
}
}
Çıktı:
i: 1
i: 2
i: 3
i: 4
public class ContinueExample {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
if (i == 3) {
continue; // 3'ü atla
}
System.out.println("i: " + i);
}
}
}
Çıktı:
i: 1
i: 2
i: 4
i: 5
Döngü Türü | Kullanım Amacı |
---|---|
for |
Sabit sayıda tekrar eder. |
while |
Koşul sağlandığı sürece tekrar eder. |
do-while |
En az bir kez çalışır, sonra koşulu kontrol eder. |
for-each |
Dizileri ve koleksiyonları gezmek için kullanılır. |
Bu üç anahtar kelime, akış kontrolüyle ilgilidir ve döngüler, metotlar ve koşullu ifadeler gibi yapılarda kullanılır. Her birinin nasıl çalıştığını detaylı örneklerle açıklayalım.
break
, genellikle döngülerin kırılması (sonlandırılması) için kullanılır. switch-case
yapılarında da kullanılır.
Çalışma Mantığı:
break
çağrıldığı anda ilgili döngüyü tamamen durdurur.- İç içe döngülerde kullanıldığında, yalnızca bulunduğu döngüyü kırar.
public class BreakExample {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
if (i == 5) {
System.out.println("Döngü 5'e ulaştı ve durduruldu.");
break; // Döngü burada sona erer.
}
System.out.println("i: " + i);
}
}
}
Çıktı:
i: 1
i: 2
i: 3
i: 4
Döngü 5'e ulaştı ve durduruldu.
i == 5
olduğundabreak
çalışır ve döngü tamamen sona erer.
public class NestedBreakExample {
public static void main(String[] args) {
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
if (j == 2) {
break; // Sadece iç döngüyü kırar
}
System.out.println("i: " + i + ", j: " + j);
}
}
}
}
Çıktı:
i: 1, j: 1
i: 2, j: 1
i: 3, j: 1
j == 2
olduğunda iç döngü sona erer, ancak dış döngü devam eder.
return
ifadesi, bir metottan değer döndürmek veya metodu tamamen sonlandırmak için kullanılır.
Çalışma Mantığı:
- Eğer bir metodun dönüş tipi
void
ise,return;
metodu erken sonlandırır. - Eğer metodun dönüş tipi bir değer içeriyorsa (int, String, boolean, vs.),
return
ile bir değer döndürmek zorunludur.
public class ReturnExample {
public static void main(String[] args) {
System.out.println("Metot çağrılıyor...");
testMetot();
System.out.println("Bu satır çalışmaz çünkü metot return ile durduruldu.");
}
public static void testMetot() {
System.out.println("Metot başladı.");
return; // Metot burada sona erer.
// System.out.println("Bu satır asla çalışmaz."); // Hata verir
}
}
Çıktı:
Metot çağrılıyor...
Metot başladı.
return;
çağrıldığı anda metot sona erer.
public class SumExample {
public static void main(String[] args) {
int result = toplama(5, 10);
System.out.println("Toplam: " + result);
}
public static int toplama(int a, int b) {
return a + b; // a + b değerini döndürür.
}
}
Çıktı:
Toplam: 15
return a + b;
ile metot, toplama işleminin sonucunu döndürür.
continue
, döngü içindeki mevcut yinelemeyi atlayarak bir sonraki tura geçmek için kullanılır. Döngüyü kırmaz, yalnızca belirtilen koşulda o adımı atlar.
Çalışma Mantığı:
continue
çağrıldığında, döngünün geri kalan kodları çalıştırılmaz ve bir sonraki iterasyona geçilir.- Genellikle belirli bir durumu atlamak için kullanılır.
public class ContinueExample {
public static void main(String[] args) {
for (int i = 1; i <= 10; i++) {
if (i % 2 != 0) { // Tek sayılar için
continue; // Döngüde kalan işlemleri atla ve bir sonraki adıma geç.
}
System.out.println("Çift sayı: " + i);
}
}
}
Çıktı:
Çift sayı: 2
Çift sayı: 4
Çift sayı: 6
Çift sayı: 8
Çift sayı: 10
i
tek sayı olduğundacontinue
çalışır ve o iterasyonun geri kalan kısmı atlanır.
public class NestedContinueExample {
public static void main(String[] args) {
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
if (j == 2) {
continue; // `j == 2` olduğunda iç döngünün bu iterasyonu atlanır.
}
System.out.println("i: " + i + ", j: " + j);
}
}
}
}
Çıktı:
i: 1, j: 1
i: 1, j: 3
i: 2, j: 1
i: 2, j: 3
i: 3, j: 1
i: 3, j: 3
j == 2
olduğundacontinue
çalışır ve o adımdaki işlemleri atlar.
Anahtar Kelime | Kullanım Alanı | Etkisi |
---|---|---|
break |
Döngüleri ve switch bloklarını kırmak için |
Döngü tamamen sona erer. |
return |
Metotlardan çıkış yapmak için | Metodu bitirir ve değer döndürür. |
continue |
Döngü içinde belirli bir iterasyonu atlamak için | O iterasyonu atlar, döngü devam eder. |
Java'da String
bir karakter dizisi (text verisi) saklamak için kullanılan sınıf (class) türüdür. Java’da String
, ilkel (primitive) bir veri tipi değildir, aksine java.lang.String
sınıfına ait bir nesnedir.
- Immutable (değiştirilemez) bir yapıya sahiptir.
- Heap üzerinde oluşturulur ve String Pool (Havuz) kullanılarak yönetilir.
+
operatörü ile birleştirme (concatenation) yapılabilir.equals()
ve==
farkı gibi önemli detayları vardır.
Java’da String
oluşturmanın iki farklı yolu vardır:
String str1 = "Merhaba"; // String literal ile oluşturuldu
String str2 = "Merhaba";
"Merhaba"
String Pool’a eklenir.- Aynı String değerini tekrar oluşturduğumuzda, hafızada yeni bir nesne oluşturulmaz, aynı referansa atanır.
- Bellek kullanımını optimize eder.
String str3 = new String("Merhaba");
String str4 = new String("Merhaba");
- Her seferinde yeni bir nesne oluşturur (Heap içinde).
- Fazladan bellek harcar, çünkü
new
ile oluşturulanString
nesneleriString Pool
kullanmaz.
📌 Karşılaştırma:
System.out.println(str1 == str2); // true (Aynı referans)
System.out.println(str3 == str4); // false (Farklı nesneler)
System.out.println(str1.equals(str3)); // true (İçerik karşılaştırması)
Java'nın String
sınıfı zengin bir metot koleksiyonuna sahiptir. Bunları detaylıca inceleyelim.
String text = "Java Programlama";
System.out.println(text.length()); // 17
String text = "Java";
System.out.println(text.charAt(0)); // J
System.out.println(text.charAt(2)); // v
String text = "Merhaba Dünya";
System.out.println(text.substring(8)); // "Dünya"
System.out.println(text.substring(0, 7)); // "Merhaba"
String text = "Java";
System.out.println(text.toUpperCase()); // "JAVA"
System.out.println(text.toLowerCase()); // "java"
String a = "Java";
String b = "java";
System.out.println(a.equals(b)); // false
System.out.println(a.equalsIgnoreCase(b)); // true
📌 Neden ==
kullanılmamalı?
==
, referansları karşılaştırır.equals()
ise içeriği karşılaştırır.
String text = "Java öğrenmek çok eğlenceli!";
System.out.println(text.contains("Java")); // true
System.out.println(text.contains("Python")); // false
String text = "Merhaba Dünya";
System.out.println(text.startsWith("Merhaba")); // true
System.out.println(text.endsWith("Dünya")); // true
String metin = "Java,Python,C++";
String[] diller = metin.split(",");
for (String dil : diller) {
System.out.println(dil);
}
Çıktı:
Java
Python
C++
String text = " Java ";
System.out.println(text.trim()); // "Java"
String text = "Java kolaydır";
System.out.println(text.replace("kolay", "harika")); // "Java harikadır"
String s1 = "Merhaba";
String s2 = " Dünya";
String sonuc = s1 + s2;
System.out.println(sonuc); // "Merhaba Dünya"
String s1 = "Java";
String s2 = " Programlama";
System.out.println(s1.concat(s2)); // "Java Programlama"
📌 String
nesneleri değiştirilemez (immutable) olduğu için, çok fazla işlem yapıldığında StringBuilder
veya StringBuffer
kullanmak daha verimlidir.
StringBuilder sb = new StringBuilder("Java");
sb.append(" Programlama");
System.out.println(sb); // "Java Programlama"
StringBuffer sb = new StringBuffer("Java");
sb.append(" Öğreniyorum");
System.out.println(sb); // "Java Öğreniyorum"
Özellik | String | StringBuilder | StringBuffer |
---|---|---|---|
Değiştirilebilir mi? | ❌ Hayır | ✅ Evet | ✅ Evet |
Hızlı mı? | 🚀 Yavaş | ⚡ Hızlı | 🔒 Daha yavaş (Thread-safe) |
Thread-Safe mi? | ❌ Hayır | ❌ Hayır | ✅ Evet |
String str1 = "Java";
String str2 = new String("Java");
System.out.println(str1 == str2); // false (Farklı referanslar)
System.out.println(str1.equals(str2)); // true (Aynı içerik)
📌 Özetle:
==
, hafızadaki referansları karşılaştırır.equals()
, içeriği karşılaştırır.
String Pool, String
nesnelerinin tekrar kullanılmasını sağlayarak bellek optimizasyonu yapar.
String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2); // true (Aynı referans)
Ama:
String str3 = new String("Hello");
System.out.println(str1 == str3); // false (Yeni nesne)
String
immutable’dır, değiştirilemez.- Karşılaştırma için
equals()
kullanılır. - Çok fazla işlem yapılacaksa
StringBuilder
tercih edilmelidir. - Bellek yönetimi için
String Pool
mekanizması vardır.
🚀 String’leri etkili kullanmak, Java programlarının performansını artırabilir! 🚀