Java Tuzakları – I: Aritmetik Yükseltmeler

Her dilde olduğu gibi Java’da da ilk görüşte son derece saçma olduğunu düşündüğümüz pek çok şey var. Aslında bu ilk bakışta saçma görünen şeylerin bazılarının ardında yatan sebepleri araştırdığınızda, o kadar da saçma olmadığını anlarsınız. Bazen ardında çok ciddi bir sebep vardır ve düşününce hak verirsiniz. Bazen o kadar iyi bir sebep yoktur ve saçmalığın, sadece dili geliştiren takımdaki geliştiriciler arsındaki belli kopukluklardan meydana geldiğini anlarsınız. Sebebi ne olursa olsun ben Java Tuzakları başlığı altında zaman zaman karşıma çıkan Java tuzaklarından bahsetmeye çalışacağım ve sebeplerini de araştırabildiğim ölçüde paylaşacağım.

İşte ilk tuzağımız, ismi “Java’da iki byte bir byte etmez”. Nasıl mı? Aşağıdaki kod parçasına bakın:

package javaturk.trick.promotion;

public class Bytes {

public static void main(String[] args) {

byte b1 = 3;
byte b2 = 2;
// byte b3 = b1 + b3;
byte b3 = (byte) (b1 + b2);

}
}

“Java’da iki byte bir byte etmez” derken kastetiğim şey, 9. satırın derleme zamanında hata verecek olması. Sebebi ise “+” operatörünün iki argumanından birisi byte, short ve char, yani “int”den küçük bir basit tip olduğunda, sonucun “int” tipine yükseltmesi. Java’da “promotion” yani yükseltme denen bu özellikten dolayı “+” her zaman en azından int bir sonuç üretir.

Java’da bu tip yükseltmeler “Numerical Promotions” olarak adlandırılır ve iki türlüdür:
Tekli yükseltmeler (unary promotion) ve ikili yükseltmeler (binary promotion). Yapılan yükseltme aslında bir genişleten çevirmedir (widening conversion) ama aynı zamanda basit tipe çevirme de (unboxing conversion) içerebilir. Yukarıdaki kod, ikili yükseltmenin genişleten çevirme ile yapılanına örnektir. İkili yükseltme şu operatörler kullanıldığında yapılır: “+”, “-“, “*”, “/”, “%”, “<", "<=", ">“, “>=”, “==”, “!=”, bit operatörleri “&”, “^”, “|” ve bazı durumlarda “?” .

Aşağıdaki örneklere bakın:

package javaturk.trick.promotion;

public class NumericBinaryPromotion {

public static void main(String[] args) {
// Ornek 1
Byte b1 = 3;
Byte b2 = 2;
// byte b3 = b1 + b2;
byte b3 = (byte) (b1 + b2); // ya da
int b4 = b1 + b2;

// Ornek 2
double d1 = 4 * Math.PI;
float f1 = 7.29f;
// float f2 = 1.0/f1;
double d2 = 1.0/f1;

// Ornek 3
Short s1 = 12;
if(s1 >= 5)
System.out.println("s1 >= 5");

// Ornek 4
char c1 = 'A';
byte b5 = 123;
// char c2 = c1 & b5;
int c2 = c1 & b5;

// Ornek 5
byte b6 = 8;
int i1 = 17;
// int i2 = (b6==0) ? i1 : 4.0f;
float f2 = (b6==0) ? i1 : 4.0f;
}
}

Yukarıdaki örneklerden de anlaşılacağı üzere ilgili operatörlerin argumanlarından birisi double ise sonuç double, değilse birisi float ise sonuç float, değilse birisi long ise sonuç long, aksi taktirde sonuç int olarak hesaplanır.

Tekli yükseltmeler ise şu operatörle yapılır: Array oluştururken ve index ile ulaşırken “[]” içinde, tekli “+” ve “-” ile bit “~” operatörlerinde ve kaydırma için “>>”, “<<" ve ">>>” operatörlerinde argümanlar ayrı ayrı olarak. Yani kaydırma operatörlerinde mesafeyi belirten argüman long ise diğer argüman long’a yükseltilmez, sadece int’e yükseltilir.

Tekli yükseltme örnekleri ise şöyle:

package javaturk.trick.promotion;

public class NumericUnaryPromotion {

public static void main(String[] args) {

// Ornek 1
byte b1 = -5;
// byte b2 = -b1;
int i1 = -b1;
// byte b2 = +b1;
int i2 = +b1;
// byte b2 = ~b1;
int i3 = ~b1;

// Ornek 2
char c1 = 5;
int[] a = new int[c1];
a[0] = -c1;

// Ornek 3
int i4 = 128;
long l = 2;
int i5 = i4 >> l; // Burada yükseltme yok

byte b3 = 8;
// byte b4 = b3 << l; int i6 = b3 << l; } }

Tüm Java'cılara tuzaksız günler 🙂

Toplam görüntülenme sayısı: 1241