Ham bir türü nedir ve neden't kullanıyoruz?
Soru:
- Java, çiğ çeşitleri nelerdir ve neden genellikle yeni bir kod içinde kullanılması gerektiğini duyuyorum?
- Eğer raw türlerini kullanabilir miyiz, bunun alternatifi nedir ve nasıl daha iyi?
Benzer sorular
CEVAP
Ham bir türü nedir?
Java Dil Belirtimi tanımlarçiğ yazınaşağıdaki gibi
JLS 4.8 Raw Types
Ham bir türü olarak tanımlar
- Genel türde bir beyan adını beraberindeki gerçek tür parametreler olmadan kullanılan.
- Bir üst sınıftan miras veya
R
superinterface olmayan ham bir türR
statik olmayan her tür üyesi.
Burada göstermek için bir örnek:
public class MyType<E> {
class Inner { }
static class Nested { }
public static void main(String[] args) {
MyType mt; // warning: MyType is a raw type
MyType.Inner inn; // warning: MyType.Inner is a raw type
MyType.Nested nest; // no warning: not parameterized type
MyType<Object> mt1; // no warning: type parameter given
MyType<?> mt2; // no warning: type parameter given (wildcard OK!)
}
}
Burada, MyType<E>
parametreli yazın(JLS 4.5). Kısaca sadece MyType
olarak halk dilinde bu tür başvurmak için yaygındır, ama teknik olarak adı MyType<E>
.
mt
tanımı da ikinci madde işareti noktası tarafından çiğ bir türü ham bir türü (ve derleme bir uyarı oluşturur) yukarıdaki ilk kurşun nokta vardır.
MyType.Nested
parametrik türü static
çünkü 16 ** üyesi, bir tür olmasına rağmen, parametrik türü değildir.
** 18 mt2
ham tipler gibi değil yani hem gerçek tür parametreleri ile bildirilir.
Çiğ türleri hakkında bu kadar özel olan ne?
Esasen, çiğ türleri jenerik tanıtıldı daha önce olduğu gibi davranır. Yani, aşağıdaki derleme zamanı tamamen yasaldır.
List names = new ArrayList(); // warning: raw type!
names.add("John");
names.add("Mary");
names.add(Boolean.FALSE); // not a compilation error!
Yukarıdaki kod gayet iyi, ama aynı zamanda aşağıdaki varsayalım: çalışır
for (Object o : names) {
String name = (String) o;
System.out.println(name);
} // throws ClassCastException!
// java.lang.Boolean cannot be cast to java.lang.String
Şimdi names
instanceof String
olmayan bir şeyi içerdiğinden çalıştırma, başımız belaya girerse,.
names
String
içermesini isterseniz muhtemelenolabilirbelki de hala ham bir türü kullanınel ile her kontrol edinadd
kendinizi, ve sonrasadece el attı27 ** names
her öğe.Hatta daha iyiama kullanmak için DEĞİL bir çiğ yazınderleyici için izin verinJava jenerik ve gücünü.
List<String> names = new ArrayList<String>();
names.add("John");
names.add("Mary");
names.add(Boolean.FALSE); // compilation error!
Eğer tabiiYAPIN** 32, ve yukarıdaki kod derleme gibi names
bildirebilirsiniz ** 31, o zaman izin vermek istiyor.
Ayrıca Bkz
Ne tür parametreleri olarak ham bir tür <Object>
kullanarak farklı
Aşağıdaki bir alıntıEtkili Java 2. Baskı, Madde 23: yeni kod çiğ türleri Yok:
Sadece 34* *ham tip 35 ** parametreli tür arasındaki fark nedir? Gevşek konuşma, ikincisi açıkça herhangi bir türdeki nesneleri tutma kapasitesine sahip olan derleyici söylerken genel tür denetimi dışında kalmayı tercih etti. Türü parametresi için
List<String>
pas yapabiliyorkenList
, 38* *türünde bir parametre için bunu yapamazsın. Jenerik için kistlerinin alt tiplerinin belirlenmesindeki kuralları vardır, veList<String>
parametreli tipList<Object>
40 ** ama çiğ değil bu tür çalışmaları devam ediyor. Sonuç olarakeğerList
ama eğer parametrik türü kullanıyorsanızList<Object>
gibi değil gibi raw kullanırsanız tipi emniyet kaybedersiniz.
Bu noktada göstermek için, List<Object>
aldığı aşağıdaki yöntemi deneyin ve new Object()
ekler.
void appendNewObject(List<Object> list) {
list.add(new Object());
}
Java jenerik değişmez. List<String>
aşağıdaki derleyici bir uyarı üretecek kadar List<Object>
bir:
List<String> names = new ArrayList<String>();
appendNewObject(names); // compilation error!
Eğer appendNewObject
çiğ bir tür parametre olarak List
ilan olsaydı, o zaman bu derleme, ve bu nedenle jenerik almış olduğunuz bu tür güvenlik kaybedersin.
Ayrıca Bkz
Nasıl ham bir tür parametre olarak <?>
kullanmadan farkı var?
*, List<String>
, *55 vb sadece List
bunun yerine onlar sadece söylemek için cazip olabilir, böylece 57**,. List<E>
add(E)
, List<?>
sadece herhangi bir rasgele nesne ekleyemezsiniz sadece tanımlar beri. ancak, büyük bir fark var: Raw türü List
tür güvenliği olmadığı için diğer taraftan, 63 ** List
bir şey.
Önceki parçacığın: aşağıdaki varyasyon göz önünde bulundurun
static void appendNewObject(List<?> list) {
list.add(new Object()); // compilation error!
}
//...
List<String> names = new ArrayList<String>();
appendNewObject(names); // this part is fine!
Derleyici olarak yazın List<?>
değişmezliği ihlal koruyan harika bir iş yaptı! Eğer raw türünü parametre olarak ilan etmiş olsaydı List list
, kod derleme ve tür List<String> names
değişmeyen ihlal edersin.
Eğer güvenli değil ise, neden bir raw yazın kullanmak için izin verilir mi?
İşte İDEA dan bir alıntı 4.8:
Ham türlerinin kullanımını sadece eski kod uyumluluk için bir imtiyaz olarak izin verilir.Kod çiğ türleri, Java programlama diline genericity girişten sonra yazılı kullanımı kesinlikle önerilmez. Java programlama dili sürümlerini ham türlerinin kullanımını engellemek mümkündür.
2. Baskı etkili Javaayrıca bu eklemek için:
Çiğ türleri kullanmamalısın o yüzden dil tasarımcılar onlara izin verdi? Uyumluluk sağlamak için.
Java platformu jenerik kullanılmaya başlandı ikinci on yılına girmek üzereydi ve jenerik kullanan varlığını Java kod büyük bir miktar vardı. Tüm bu kod jenerik kullanan yeni bir kod ile yasal ve birlikte kalan kritik olarak görüldü. Yasal olması için sıradan bir tip ile kullanmak için, ve tam tersi tasarlanmış yöntemler parametreli türler örnekleri geçmesi gerekiyordu. Bu gereksinim, olarak bilinirgöç uyumlulukraw türlerini destekleme kararı sürdü.
Özetle, çiğ türleri ASLA yeni bir kod kullanılmalıdır.Her zaman parametreli türleri kullanmalısınız.
Hiç istisna yok mu?
Java jenerik olmayan şeyleşiyor, çünkü ne yazık ki, çiğ türleri yeni bir kod kullanılmalıdır iki istisnası vardır:
- Sınıf rakamları
List.class
örneğin,List<String>.class
değil instanceof
,o instanceof Set
örneğin,o instanceof Set<String>
değil işlenen
İnputStream & Çıkış Akışı nedir? Neden...
Doğru JSON içerik türü nedir?...
Bir serialVersionUİD nedir ve neden ku...
Yansıma nedir ve neden yararlıdır?...
Neden Python kodunu daha hızlı bir işl...