Otomatik kutudan çıkarma konusunda Java 6 ile Java 7 arasındaki farklar


107

Java SE 6 ve Java SE 7 arasında otomatik kutudan çıkarma davranışında bir fark olduğunu fark ettim. Bunun neden olduğunu merak ediyorum, çünkü bu iki sürüm arasında bu davranışta herhangi bir değişiklik belgesi bulamıyorum.

İşte basit bir örnek:

Object[] objs = new Object[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];

Bu, Java SE 7'den javac ile iyi derlenir. Ancak, derleyiciye "-source 1.6" argümanını verirsem, son satırda bir hata alıyorum:

inconvertible types
found   : java.lang.Object
required: int

Yerel sürüm 6 derleyicisiyle derlemek için Java SE 6'yı indirmeyi denedim (kaynak seçeneği olmadan). Yukarıdakiyle aynı hatayı kabul eder ve verir.

Peki ne verir? Daha fazla deneyden, Java 6'daki kutudan çıkarmanın yalnızca kutulu tipte olduğu açıkça (derleme zamanında) olan değerleri açabileceği görülmektedir. Örneğin, bu her iki sürümde de çalışır:

Integer[] objs = new Integer[2];
objs[0] = new Integer(5);
int myInt = (int)objs[0];

Öyleyse, Java 6 ve 7 arasında, kutudan çıkarma özelliği, değerin uygun kutulu tipte olduğunu bilmeden (derleme zamanında) tek seferde nesne türlerini çevirip kutudan çıkarabilecek şekilde geliştirildi. Bununla birlikte, Java Dil Spesifikasyonunu veya Java 7 çıktığında yazılan blog gönderilerini okurken, bu şeyde herhangi bir değişiklik göremiyorum, bu yüzden değişikliğin ne olduğunu ve bu "özelliğin" ne olduğunu merak ediyorum ?

Sadece bir merak: Değişiklik nedeniyle, "yanlış" kutudan çıkarmaları tetiklemek mümkündür:

Object[] objs = new Float[2];
objs[0] = new Float(5);
int myInt = (int)objs[0];

Bu iyi derler ancak çalışma zamanında bir ClassCastException verir.

Bununla ilgili herhangi bir referans var mı?


17
İlginç. Otomatik kutulama karmaşası için yeni bir bileşen. Bir dizi yerine tek bir nesne ile örneğinizin daha basit ve net olabileceğini düşünüyorum. Integer obj = new Integer(2); int x = (int)obj;: Java 7'de çalışıyor, Java 6'da hata veriyor.
leonbloy

1
Hangi JDK'yı kullanıyorsunuz? Bunun farklı satıcılarla da ilgisi olabilir ...
barfu,

1
@leonbloy: Basitleştirme hakkında iyi bir nokta, biraz basitleştirdim (orijinal kodumdan) ama bir şekilde çok erken bıraktım!
Morty

@Thomas: Kullandığım Oracle'dan en son JDK idi (her sürüm için).
Morty

2
Otomatik kutuyu asla kullanmamak için başka bir neden.
gyorgyabraham

Yanıtlar:


92

Görünüşe göre, bölüm 5.5 Java 7 JLS'nin Döküm Dönüşümü'ndeki dil , muhtemelen izin verilen dönüşümleri açıklığa kavuşturmak için Java 5/6 JLS'deki aynı bölüme kıyasla güncellendi .

Java 7 JLS diyor

Bir referans türünün bir ifadesi, dönüştürme kutusunun kaldırılmasıyla hatasız bir ilkel türe dönüştürme işlemine tabi tutulabilir.

Java 5/6:

Bir referans türünün bir değeri, dönüştürme kutusunun kaldırılmasıyla ilkel bir türe dönüştürülebilir (§5.1.8).

Java 7 JLS ayrıca referans türlerinden ilkellere izin verilen dönüşümlerin (bu tablo Java 5/6 JLS'ye dahil edilmemiştir) bir tablosunu (tablo 5.1) içerir. Bu, kutudan çıkarmayla daraltılmış bir referans dönüştürme olarak Object'ten ilkellere dönüştürmeleri açık bir şekilde listeler.

Nedeni bu e-postada açıklanmıştır :

Alt satır: Spesifikasyon ise. (Object) (int) 'e izin verir (int) (Object).


35

Haklısın; daha basitçe söylemek gerekirse:

Object o = new Integer(1234);
int x = (int) o;

Bu Java 7'de çalışır, ancak Java 6 ve altında bir derleme hatası verir. Garip bir şekilde, bu özellik belirgin bir şekilde belgelenmemiştir; örneğin burada bahsedilmiyor . Yeni bir özellik mi yoksa bir hata düzeltmesi mi (veya yeni bir hata mı?) Tartışmalı , bazı ilgili bilgilere ve tartışmaya bakın . Mutabakat , orijinal spesifikasyondaki bir belirsizliğe işaret ediyor gibi görünüyor , bu da 7'de düzeltilen Java 5 / 6'da biraz yanlış / tutarsız uygulamaya yol açtı, çünkü JSR 292'nin (Dinamik Olarak Yazılan Diller) uygulanması için kritikti.

Java otomatik kutulama artık bazı tuzaklara ve sürprizlere sahip. Örneğin

Object obj = new Integer(1234);
long x = (long)obj;

derlenir, ancak ClassCastExceptionçalışma zamanında başarısız olur (ile ). Bunun yerine bu işe yarayacaktır:

long x = (long)(int)obj;


2
Cevap için teşekkürler. Ancak anlamadığım bir şey var. Bu, JLS'nin ve beraberindeki uygulamaların bir açıklamasıdır (bkz. Posta tartışması), ancak bu, JVM'deki diğer yazılı dilleri barındırmak için neden yapılsın? Sonuçta, bu VM'de değil, dilde bir değişikliktir: VM'nin çevrim davranışı her zaman olduğu gibi çalışır, derleyici bu özelliği Tamsayı'ya çevrim ve .intValue () çağırmak için mevcut mekanizmayı kullanarak uygular. Peki, Java dilindeki bu değişiklik sanal makinede diğer dillerin çalıştırılmasına nasıl yardımcı olabilir? Bağlantınızın bunu önerdiğine katılıyorum, sadece merak ediyorum.
Morty
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.