1. Değişkenleri başlatma

Bildiğiniz gibi, sınıfınızda birkaç değişken bildirebilir ve yalnızca bunları bildirmekle kalmaz, aynı zamanda bunları ilk değerleri ile hemen başlatabilirsiniz.

Ve aynı değişkenler bir kurucuda da başlatılabilir. Bu, teorik olarak, bu değişkenlere iki kez değer atanabileceği anlamına gelir. Örnek

kod Not
class Cat
{
   public String name;
   public int age = -1;

   public Cat(String name, int age)
   {
     this.name = name;
     this.age = age;
   }

   public Cat()
   {
     this.name = "Nameless";
   }
}



Değişkene agebir başlangıç ​​değeri atanır




Başlangıç ​​değerinin üzerine yazılır


Yaş değişkeni başlangıç ​​değerini saklar.
Cat cat = new Cat("Whiskers", 2);
Buna izin verilir: ilk kurucu çağrılacak
Cat cat = new Cat();
Buna izin verilir: ikinci kurucu çağrılacak

Cat cat = new Cat("Whiskers", 2);Yürütüldüğünde böyle olur :

  • bir Catnesne yaratıldı
  • Tüm örnek değişkenleri başlangıç ​​değerleriyle başlatılır
  • Yapıcı çağrılır ve kodu yürütülür.

Başka bir deyişle, değişkenler önce ilk değerlerini alır ve ancak o zaman yapıcının kodu çalıştırılır.


2. Bir sınıftaki değişkenlerin başlangıç ​​sırası

Değişkenler yalnızca yapıcı çalıştırılmadan önce başlatılmazlar - iyi tanımlanmış bir sırayla başlatılırlar: sınıfta bildirildikleri sıra.

Bazı ilginç kodlara bakalım:

kod Not
public class Solution
{
   public int a = b + c + 1;
   public int b = a + c + 2;
   public int c = a + b + 3;
}

Bu kod derlenmeyecek, çünkü değişken yaratıldığı sırada henüz  ve değişkenleri ayok  . Ancak kodunuzu aşağıdaki gibi yazabilirsiniz — bu kod derlenecek ve gayet iyi çalışacaktır .bc

kod Not
public class Solution
{
   public int a;
   public int b = a + 2;
   public int c = a + b + 3;
}


0
0+2
0+2+3

Ancak kodunuzun diğer geliştiriciler için şeffaf olması gerektiğini unutmayın. Kodun okunabilirliğini bozacağı için bu tür teknikleri kullanmamak daha iyidir.

Burada, değişkenlere bir değer atanmadan önce, varsayılan bir değere sahip olduklarını hatırlamalıyız . Tip için intbu sıfırdır.

JVM değişkeni başlattığında a, basitçe int türü için varsayılan değeri atayacaktır: 0.

değerine ulaştığında b, a değişkeni zaten bilinecek ve bir değere sahip olacaktır, bu nedenle JVM ona 2 değerini atayacaktır.

Ve değişkene ulaştığında c, ave bdeğişkenleri zaten başlatılacaktır, böylece JVM, c: 0+2+3 için başlangıç ​​değerini kolayca hesaplayacaktır.

Bir yöntemin içinde bir değişken oluşturursanız, ona daha önce bir değer atamadıysanız onu kullanamazsınız. Ancak bu, bir sınıfın değişkenleri için doğru değil! Bir sınıfın değişkenine bir başlangıç ​​değeri atanmamışsa, varsayılan bir değer atanır.


3. Sabitler

Nesnelerin nasıl yaratıldığını incelerken, sabitlerin, yani değiştiricili değişkenlerin başlatılmasına değinmekte fayda var final.

Bir değişken değiştiriciye sahipse final, o zaman bir başlangıç ​​değeri atanmalıdır. Bunu zaten biliyorsunuz ve bunda şaşılacak bir şey yok.

Ancak bilmediğiniz şey, kurucuda atarsanız, ilk değeri hemen atamanız gerekmediğidir. Bu, son bir değişken için gayet iyi çalışacaktır. Tek gereksinim, birden çok kurucunuz varsa, her kurucuda bir son değişkene bir değer atanmalıdır.

Örnek:

public class Cat
{
   public final int maxAge = 25;
   public final int maxWeight;

   public Cat (int weight)
   {
     this.maxWeight = weight; // Assign an initial value to the constant
   }
}


4. Bir yapıcıda kod

Ve inşaatçılar hakkında birkaç önemli not daha. Daha sonra, Java öğrenmeye devam ettikçe, kalıtım, serileştirme, istisnalar vb. şeylerle karşılaşacaksınız. Bunların tümü, kurucuların çalışmalarını değişen derecelerde etkiler. Şimdi bu konulara derinlemesine dalmanın bir anlamı yok ama en azından bunlara değinmek zorundayız.

Örneğin, burada inşaatçılar hakkında önemli bir açıklama var. Teorik olarak, bir kurucuda herhangi bir karmaşıklığın kodunu yazabilirsiniz. Ama bunu yapma. Örnek:

class FilePrinter
{
   public String content;

   public FilePrinter(String filename) throws Exception
   {
      FileInputStream input = new FileInputStream(filename);
      byte[] buffer = input.readAllBytes();
      this.content = new String(buffer);
   }

   public void printFile()
   {
      System.out.println(content);
   }
}






Bir dosya okuma akışı açın
Dosyayı bir bayt dizisine okuyun
Bayt dizisini bir dize olarak kaydedin




Dosyanın içeriğini ekranda görüntüleyin

FilePrinter sınıfı yapıcısında, bir dosya üzerinde hemen bir bayt akışı açtık ve içeriğini okuduk. Bu karmaşık bir davranıştır ve hatalara neden olabilir.

Ya böyle bir dosya olmasaydı? Dosyayı okumayla ilgili sorunlar olursa ne olur? Ya çok büyük olsaydı?

Karmaşık mantık, yüksek hata olasılığı anlamına gelir ve bu, kodun istisnaları doğru bir şekilde işlemesi gerektiği anlamına gelir.

Örnek 1 — Serileştirme

Standart bir Java programında, sınıfınızın nesnelerini yaratan kişinin siz olmadığınız pek çok durum vardır. Örneğin, ağ üzerinden bir nesne göndermeye karar verdiğinizi varsayalım: bu durumda, Java makinesinin kendisi nesnenizi bir bayt kümesine dönüştürecek, gönderecek ve nesneyi bayt kümesinden yeniden oluşturacaktır.

Ancak, dosyanızın diğer bilgisayarda bulunmadığını varsayalım. Yapıcıda bir hata olacak ve kimse bununla ilgilenmeyecek. Ve bu, programın sona ermesine neden olabilir.

Örnek 2 — Bir sınıfın alanlarını başlatma

Sınıf oluşturucunuz işaretli istisnalar atabiliyorsa, yani throws anahtar sözcüğüyle işaretlenmişse, belirtilen istisnaları nesnenizi oluşturan yöntemde yakalamanız gerekir.

Peki ya böyle bir yöntem yoksa? Örnek:

kod  Not
class Solution
{
   public FilePrinter reader = new FilePrinter("c:\\readme.txt");
}
Bu kod derlenmeyecek.

Sınıf yapıcısı işaretli bir istisnaFilePrinter atabilir , bu da bir try-catch bloğuna sarmadan bir nesne yaratamayacağınız anlamına gelir . Ve bir try-catch bloğu yalnızca bir yöntemde yazılabilir.FilePrinter



5. Temel sınıf yapıcısı

Önceki derslerde kalıtımdan biraz bahsetmiştik. Ne yazık ki, kalıtım ve OOP hakkındaki tam tartışmamız, OOP'ye ayrılmış seviye için ayrılmıştır ve kurucuların kalıtımı bizim için zaten alakalıdır.

Sınıfınız başka bir sınıfı miras alırsa, üst sınıfın bir nesnesi, sınıfınızın bir nesnesinin içine gömülür. Dahası, ana sınıfın kendi değişkenleri ve kendi oluşturucuları vardır.

Bu, sınıfınızda bir üst sınıf olduğunda ve değişkenlerini ve yöntemlerini devraldığınızda, değişkenlerin nasıl başlatıldığını ve kurucuların nasıl çağrıldığını bilmeniz ve anlamanız çok önemli olduğu anlamına gelir.

sınıflar

Değişkenlerin başlatıldığı ve yapıcıların çağrıldığı sırayı nasıl bilebiliriz? İki sınıf için kod yazarak başlayalım. Biri diğerini devralacak:

kod Not
class ParentClass
{
   public String a;
   public String b;

   public ParentClass()
   {
   }
}

class ChildClass extends ParentClass
{
   public String c;
   public String d;

   public ChildClass()
   {
   }
}










Sınıf , sınıfı ChildClass miras alır ParentClass.

Değişkenlerin başlatıldığı ve yapıcıların çağrıldığı sırayı belirlememiz gerekiyor. Günlük kaydı, bunu yapmamıza yardımcı olacaktır.

Kerestecilik

Günlüğe kaydetme, bir program tarafından çalışırken gerçekleştirilen eylemleri konsola veya bir dosyaya yazarak kaydetme işlemidir.

Yapıcının çağrılıp çağrılmadığını belirlemek oldukça basittir: yapıcının gövdesinde konsola bir mesaj yazın. Ancak bir değişkenin başlatılıp başlatılmadığını nasıl anlarsınız?

Aslında bu da çok zor değil: değişkeni başlatmak için kullanılan değeri döndürecek ve başlatmayı günlüğe kaydedecek özel bir yöntem yazın. Kod şöyle görünebilir:

son kod

public class Main
{
   public static void main(String[] args)
   {
      ChildClass obj = new ChildClass();
   }

   public static String print(String text)
   {
      System.out.println(text);
      return text;
   }
}

class ParentClass
{
   public String a = Main.print("ParentClass.a");
   public String b = Main.print("ParentClass.b");

   public ParentClass()
   {
      Main.print("ParentClass.constructor");
   }
}

class ChildClass extends ParentClass
{
   public String c = Main.print("ChildClass.c");
   public String d = Main.print("ChildClass.d");

   public ChildClass()
   {
      Main.print("ChildClass.constructor");
   }
}




ChildClassNesne oluşturma


Bu yöntem, iletilen metni konsola yazar ve ayrıca döndürür. Display text sınıfını





bildirin ve değişkenleri bununla birlikte başlatın. Yapıcının çağrıldığına dair bir mesaj yazın. Dönüş değerini dikkate almayın. Display text sınıfını bildirin ve değişkenleri bununla birlikte başlatın. Yapıcının çağrıldığına dair bir mesaj yazın. Dönüş değerini dikkate almayın. ParentClass









ChildClass






Bu kodu çalıştırırsanız, ekranda aşağıdaki gibi bir metin görüntülenecektir:

Yöntemin konsol çıktısıMain.print()
ParentClass.a
ParentClass.b
ParentClass.constructor
ChildClass.c
ChildClass.d
ChildClass.constructor

Böylece, yapıcı çağrılmadan önce bir sınıfın değişkenlerinin başlatıldığından her zaman kişisel olarak emin olabilirsiniz. Bir temel sınıf, miras alınan sınıfın başlatılmasından önce tam olarak başlatılır.