1. Tüm sınıflar miras alırObject

Java'daki tüm sınıflar, Objectsı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
Object o = new Scanner(System.in);
Değişken , bir nesneye oreferans depolarScanner
Object o = new String();
Değişken , bir nesneye oreferans depolarString
Object o = new Integer(15);
Değişken , bir nesneye oreferans depolarInteger
Object o = "Hello";
Değişken , bir nesneye oreferans 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
Object o = new Scanner(System.in);
int x = o.nextInt();
Program derlenmeyecek. Sınıfın bir yöntemi Objectyoktur nextInt().
Object o = new Scanner(System.in);

Scanner console = (Scanner) o;

int x = console.nextInt();
Bu çalışacak. Burada, bir typecast operatörü kullanarak bir değişkendeki bir nesneye

yapılan referansı kaydediyoruz . ScannerScanner

Değişken bir nesneye referans depolasa Objectbile gidip bir Tarayıcı değişkenine bir değişken atayamazsınız . ObjectScannerAncak 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 name1bir değişkenin adı Typeve bir nesneye referans depolayan name2bir değişkenin adıdır .ObjectType

daktilo

Değişkenin tipi ile nesnenin tipi eşleşmezse a ClassCastExceptionfırlatılır. Örnek:

kod Not
Object o = new Integer(5);
String s = (String) o;
Çalışma zamanında bir hata oluşacak: buraya
bir a ClassCastExceptionatı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 instanceofolmadığını kontrol eder .nameType

Örnek olarak, çeşitli nesneler dizisinde bir dize bulalım:

kod Not
Object[] objects = {10, "Hello", 3.14};

for (int i = 0; i < objects.length; i++)
{
   if (objects[i] instanceof String)
   {
      String s = (String) objects[i];
      System.out.println(s);
   }
}
IntegerOtomatik kutulama, bu değerleri sırasıyla bir , Stringve 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. ObjectBö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
ArrayList numbers = new ArrayList();


for (int i = 0; i < 10; i++)
   numbers.add(i * 10);


int sum = 0;
for (int i = 0; i < 10; i++)
{
   sum = sum + (Integer) numbers.get(i);
}
ObjectNesnelere 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
ArrayList numbers = new ArrayList();


for (int i = 0; i < 10; i++)
   numbers.add(i * 2.5);


int sum = 0;
for (int i = 0; i < 10; i++)
{
   sum = sum + (Integer) numbers.get(i);
}
ObjectNesnelere 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.02.55.0





DoubleInteger

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'daki 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
ArrayList<Integer> list;
değişken oluşturma
list = new ArrayList<Integer> ();
nesne oluşturma
ArrayList<Integer>[] array;
Diziler oluşturma

Böyle bir koleksiyonda yalnızca Integerdeğişkenler saklanabilir:

kod Tanım
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(new Integer(1));
list.add(2);
list.add("Hello");
ArrayListIntegeröğ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
ArrayList<Integer> list = new ArrayList<Integer>();
ArrayList list = new ArrayList();
list.add(1);
list.add( (Integer) 1 );
int x = list.get(0);
int x = (Integer) list.get(0);
list.set(0, 10);
list.set(0, (Integer) 10);

Bir tamsayı koleksiyonundaki sayıları toplayan bir yöntemimiz olduğunu varsayalım:

kod derleyici ne yapar
public int sum(ArrayList<Integer> numbers)
{
   int result = 0;

   for (int i = 0; i < numbers.size(); i++)
      result = result + numbers.get(i);

   return result;
}
public int sum(ArrayList numbers)
{
   int result = 0;

   for (int i = 0; i < numbers.size(); i++)
      result = result + (Integer) numbers.get(i);

   return result;
}

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 intan'a Integerve 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
HashMap<Integer, String> map = new HashMap<Integer, String>();
map.put(7, "Hello");
map.put(-15, "Hello");
Yöntemin putilk 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
ArrayList<String>[] list = new ArrayList<String>[10];
StringArrayList[] list = new StringArrayList[10];
ArrayList<Integer>[] list = new ArrayList<Integer>[10];
IntegerArrayList[] list = new IntegerArrayList[10];
ArrayList<Scanner>[] list = new ArrayList<Scanner>[10];
ScannerArrayList[] list = new ScannerArrayList[10];