1. Tüm sınıflar miras alırObject
Java'daki tüm sınıflar, Object
sınıfı dolaylı olarak devralır.
Java Core görevinde kalıtımın ne olduğunu ve Java'da nasıl çalıştığını inceleyeceğiz. Şimdilik, bundan çıkan basit bir gerçeği ele alacağız:
Herhangi bir sınıftan bir nesne bir değişkene atanabilir Object
. Örnek:
kod | Not |
---|---|
|
Değişken , bir nesneye o referans depolarScanner |
|
Değişken , bir nesneye o referans depolarString |
|
Değişken , bir nesneye o referans depolarInteger |
|
Değişken , bir nesneye o referans depolarString |
İyi haber burada bitiyor. Derleyici , bir değişkende kaydedilen orijinal nesne türünü izlemezObject
, bu nedenle kaydedilen nesnede sınıfın yöntemleri dışında yöntemleri çağıramazsınız .Object
Nesnenin orijinal türüyle ilişkili yöntemleri çağırmanız gerekirse, önce doğru türde bir değişkene bir başvuru kaydetmeniz ve ardından bu değişkendeki yöntemleri çağırmanız gerekir:
kod | Not |
---|---|
|
Program derlenmeyecek. Sınıfın bir yöntemi Object yoktur nextInt() . |
|
Bu çalışacak. Burada, bir typecast operatörü kullanarak bir değişkendeki bir nesneye yapılan referansı kaydediyoruz . Scanner Scanner |
Değişken bir nesneye referans depolasa Object
bile gidip bir Tarayıcı değişkenine bir değişken atayamazsınız . Object
Scanner
Ancak bunu zaten bildiğiniz typecast operatörünü kullanırsanız yapabilirsiniz . Bu onun genel görünüşüdür:
Type name1 = (Type) name2;
Nerede name1
bir değişkenin adı Type
ve bir nesneye referans depolayan name2
bir değişkenin adıdır .Object
Type
daktilo
Değişkenin tipi ile nesnenin tipi eşleşmezse a ClassCastException
fırlatılır. Örnek:
kod | Not |
---|---|
|
Çalışma zamanında bir hata oluşacak: buraya bir a ClassCastException atılacak |
Java'da bu hatayı önlemenin bir yolu var: Bunu bir değişkende depolanan nesnenin türünü kontrol ederek yapıyoruz :
name instanceof Type
Operatör , değişkenin bir nesne olup instanceof
olmadığını kontrol eder .name
Type
Örnek olarak, çeşitli nesneler dizisinde bir dize bulalım:
kod | Not |
---|---|
|
Integer Otomatik kutulama, bu değerleri sırasıyla bir , String ve olarak dönüştürür Double . Nesne dizisi üzerinde döngü yapın Nesne bir değişken ise String Onu bir değişkene kaydedin Değişkeni ekranda görüntüleyin. String |
2. Jenerik ilaçlar neden ortaya çıktı — koleksiyonlar
Koleksiyonlara dönelim.
Java geliştiricileri sınıfı oluşturur oluşturmaz ArrayList
, onu evrensel yapmak istediler, böylece her tür nesneyi depolayabilirdi. Object
Böylece öğeleri depolamak için bir s dizisi kullandılar .
Bu yaklaşımın gücü, koleksiyona herhangi bir türde nesne ekleyebilmenizdir.
Tabii ki, birkaç zayıflık var.
dezavantaj 1.
Bir koleksiyondan öğeler alınırken bir tür dönüştürme işleci yazmak her zaman gerekliydi:
kod | Not |
---|---|
|
Object Nesnelere referansları depolamak için bir koleksiyon oluşturun Koleksiyonu sayılarla doldurun 10 , 20 , ... 100 ; Koleksiyonun öğelerini toplayın Typecasting gereklidir |
dezavantaj 2.
Bir koleksiyonun belirli bir öğe türü içerdiğine dair bir garanti yoktu.
kod | Not |
---|---|
|
Object Nesnelere referansları depolamak için bir koleksiyon oluşturun Koleksiyonu nesneler olarak temsil edilen sayılarla dolduruyoruz : , , , ... Koleksiyonun öğelerini toplayın Bir hata olacaktır: a, an'a dönüştürülemez. Double 0.0 2.5 5.0 Double Integer |
Veriler herhangi bir yerde koleksiyona eklenebilir:
- başka bir yöntemde
- başka bir programda
- bir dosyadan
- ağ üzerinden
dezavantaj 3.
Koleksiyondaki veriler yanlışlıkla değiştirilebilir.
Verilerinizle dolu bir koleksiyonu bir yönteme iletebilirsiniz. Farklı bir programcı tarafından yazılan bu yöntem, verilerini koleksiyonunuza ekler.
Koleksiyonun adı, içinde hangi tür verilerin saklanabileceğini açıkça belirtmiyor. Ve değişkeninize net bir isim verseniz bile, ona bir referans bir düzine yönteme iletilebilir ve bu yöntemler kesinlikle değişkenin orijinal adı hakkında hiçbir şey bilmeyecektir.
3. Jenerikler
Java'da, tüm bu sorunlar jenerik adı verilen bu harika şey tarafından ortadan kaldırılır.
Java'da jenerik, türlere tür parametreleri ekleme yeteneği anlamına gelir. Sonuç, karmaşık bir bileşik tiptir. Böyle bir bileşik türün genel görünümü şudur:
ClassName<TypeParameter>
Bu genel bir sınıftır. Ve normalde sınıfları kullandığınız her yerde kullanılabilir.
kod | Tanım |
---|---|
|
değişken oluşturma |
|
nesne oluşturma |
|
Diziler oluşturma |
Böyle bir koleksiyonda yalnızca Integer
değişkenler saklanabilir:
kod | Tanım |
---|---|
|
ArrayList Integer öğelerle koleksiyon Buna izin verilir Ve bu da işe yarayacak
otomatik kutulama
Ancak buna izin verilmiyor: derleme hatası |
Java Koleksiyonları görevinde tür parametreleriyle kendi sınıflarınızı nasıl oluşturacağınızı öğreneceksiniz. Şimdilik, bunların nasıl kullanılacağına ve nasıl çalıştıklarına bakacağız.
4. Jenerik ilaçlar nasıl çalışır?
Aslında, jenerikler çok ilkeldir.
Derleyici, genel türleri sıradan türlerle değiştirir. Ancak, genel türdeki yöntemler kullanıldığında, derleyici, tür parametrelerine parametreler atamak için bir tür belirleme işleci ekler:
kod | derleyici ne yapar |
---|---|
|
|
|
|
|
|
|
|
Bir tamsayı koleksiyonundaki sayıları toplayan bir yöntemimiz olduğunu varsayalım:
kod | derleyici ne yapar |
---|---|
|
|
Başka bir deyişle, jenerikler bir tür sözdizimsel şekerdir, tıpkı otomatik kutulama gibi, ama biraz daha fazlası. Otomatik kutulama ile derleyici, an'yi int
an'a Integer
ve tersine dönüştürmek için yöntemler ekler ve jenerikler için tip belirleme işleçleri ekler.
Derleyici, genel sınıflarınızı tür parametreleriyle derledikten sonra, bunlar yalnızca sıradan sınıflara ve yazım işleçlerine dönüştürülür. Genel türdeki değişkenlere iletilen tür bağımsız değişkenleriyle ilgili bilgiler kaybolur. Bu efekt aynı zamanda tip silme olarak da adlandırılır .
Bazen genel sınıflar (tür parametreli sınıflar) yazan programcılar, argüman olarak iletilen türler hakkındaki bilgilere gerçekten ihtiyaç duyarlar. Java Collections görevinde, bununla nasıl başa çıkacağınızı ve bunun ne anlama geldiğini öğreneceksiniz.
5. Jenerikler hakkında birkaç gerçek
İşte jenerikler hakkında bazı daha ilginç gerçekler.
Sınıflar birkaç tür parametresine sahip olabilir. Şunun gibi görünüyor:
ClassName<TypeParameter1, TypeParameter2, TypeParameter3>
Aslında bu pek de şaşırtıcı değil. Derleyicinin bir türe yayınlamak için bir işleç ekleyebildiği her yerde, birden çok tür belirleme işleci ekleyebilir.
Örnekler:
kod | Not |
---|---|
|
Yöntemin put ilk parametresi bir Integer , ikincisi ise birString |
Genel tipler parametre olarak da kullanılabilir . Şunun gibi görünüyor:
ClassName<TypeParameter<TypeParameterParameter>>
Dize listelerini saklayacak bir liste oluşturmak istediğimizi varsayalım. Bu durumda, şöyle bir şey elde ederiz:
// List of greetings
ArrayList<String> listHello = new ArrayList<String>();
listHello.add ("Hello");
listHello.add ("Hi");
// List of goodbyes
ArrayList<String> listBye = new ArrayList<String>();
listBye.add("Bye");
listBye.add ("Goodbye");
// List of lists
ArrayList<ArrayList<String>> lists = new ArrayList<ArrayList<String>>();
lists.add(listHello);
lists.add(listBye);
Dizi türleri olarak genel türler (tür parametreli türler) de kullanılabilir. Şuna benzer:
ClassName<TypeParameter>[] array = new ClassName<TypeParameter>[size];
Burada sihirli bir şey olmuyor: köşeli parantezler sadece tür adını gösteriyor:
kod | Jenerik olmayan muadili |
---|---|
|
|
|
|
|
|