1. Özellikler: alıcılar ve ayarlayıcılar

Aynı anda düzinelerce programcı tarafından büyük bir proje geliştirilirken, sınıf alanlarında depolanan verileri farklı şekilde işlerlerse sorunlar sıklıkla ortaya çıkar.

Belki insanlar sınıf belgelerini ayrıntılı olarak incelemekte başarısız olurlar veya belki de her vakayı açıklamaz. Sonuç olarak, bir nesnenin dahili verilerinin "bozulup" nesneyi geçersiz kılabileceği sık durumlar vardır.

Bu durumlardan kaçınmak için, Java'da tüm sınıf alanlarını özel yapmak alışılmış bir durumdur . Yalnızca sınıfın yöntemleri, sınıfın değişkenlerini değiştirebilir. Diğer sınıflardan hiçbir yöntem değişkenlere doğrudan erişemez.

Diğer sınıfların, sınıfınızın nesnelerinin içindeki verileri alabilmesini veya değiştirebilmesini istiyorsanız, sınıfınıza iki yöntem eklemeniz gerekir - bir get yöntemi ve bir set yöntemi. Örnek:

kod Not
class Person
{
   private String name;

   public Person(String name)
   {
      this.name = name;
   }

   public String getName()
   {
      return name;
   }

   public void setName(String name)
   {
      this.name = name;
   }
}


privateisim alanı



Alanın yapıcı aracılığıyla başlatılması


getName()— Bu yöntem, ad alanının değerini döndürür




setName()— Bu yöntem, ad alanının değerini değiştirir

Başka hiçbir sınıf, name alanının değerini doğrudan değiştiremez. getName() Birisinin name alanının değerini alması gerekiyorsa, yöntemi bir nesne üzerinde çağırması gerekir Person. setName() Bazı kodlar, ad alanının değerini değiştirmek isterse, yöntemi bir nesne üzerinde çağırması gerekir Person.

Yöntem ayrıca " ad alanı için alıcıgetName() " olarak da adlandırılır ve yöntem " ad alanı için ayarlayıcı " olarak adlandırılır .setName()

Bu çok yaygın bir yaklaşımdır. Java kodunun %80-90'ında, bir sınıfta genel değişkenleri asla görmezsiniz. privateBunun yerine, (veya ) olarak bildirilecekler protectedve her değişkenin genel alıcıları ve ayarlayıcıları olacaktır.

Bu yaklaşım, kodu daha uzun ama daha güvenilir hale getirir.

Bir sınıf değişkenine doğrudan erişmek , arabanızı çift sarı çizgiden döndürmek gibidir : daha kolay ve daha hızlıdır, ancak bunu herkes yaparsa, işler herkes için daha da kötüleşir.

Diyelim ki bir noktayı ( x, y) tanımlayan bir sınıf oluşturmak istiyorsunuz. Acemi bir programcının bunu nasıl yapacağı aşağıda açıklanmıştır:

class Point
{
   public int x;
   public int y;
}

Deneyimli bir Java programcısı bunu şu şekilde yapar:

kod
class Point {
   private int x;
   private int y;

   public Point(int x, int y) {
      this.x = x;
      this.y = y;
   }

   public int getX() {
      return x;
   }

   public void setX(int x) {
      this.x = x;
   }

   public int getY() {
      return y;
   }

   public void setY(int y) {
      this.y = y;
   }
}

Kod daha mı uzun? şüphesiz.

Ancak alıcılara ve ayarlayıcılara parametre doğrulaması ekleyebilirsiniz. xÖrneğin, ve ydeğerlerinin her zaman sıfırdan büyük olduğundan (veya sıfırdan küçük olmadığından) emin olabilirsiniz . Örnek:

kod Not
class Point {
   private int x;
   private int y;

   public Point(int x, int y) {
      this.x = x < 0 ? 0 : x;
      this.y = y < 0 ? 0 : y;
   }

   public int getX() {
      return x;
   }

   public void setX(int x) {
      this.x = x < 0 ?  0 : x;
   }

   public int getY() {
      return y;
   }

   public void setY(int y) {
      this.y = y < 0 ? 0 : y;
   }
}


2. Nesne ömrü

Nesnelerin işleç kullanılarak oluşturulduğunu zaten biliyorsunuz new, ancak nesneler nasıl silinir? Sonsuza dek var olmazlar. Bunun için yeterli hafıza yok.

C++ gibi birçok programlama dilinde deletenesneleri silmek için özel bir operatör vardır. Ancak bu Java'da nasıl çalışır?

Java'da her şey biraz farklı düzenlenmiştir. Java'da silme işleci yoktur. Bu, nesnelerin Java'da silinmediği anlamına mı geliyor? Hayır, elbette silinirler. Aksi takdirde, Java uygulamalarının belleği hızla tükenir ve programların kesintisiz çalıştığı aylarca konuşulmaz.

Java'da nesnelerin silinmesi tamamen otomatiktir. Java makinesinin kendisi nesnelerin silinmesini gerçekleştirir. Bu işleme çöp toplama, çöpü toplayan mekanizmaya da çöp toplayıcı ( GC ) denir .

Peki Java makinesi bir nesnenin ne zaman silineceğini nasıl biliyor?

Çöp toplayıcı, tüm nesneleri "ulaşılabilir" ve "ulaşılamaz" olarak ayırır. Bir nesneye en az bir başvuru varsa, erişilebilir olarak kabul edilir. Bir nesneye atıfta bulunan bir değişken yoksa, nesne ulaşılamaz olarak kabul edilir ve çöp ilan edilir, bu da silinebileceği anlamına gelir.

Java'da varolan bir nesneye başvuru oluşturamazsınız; yalnızca zaten sahip olduğunuz başvuruları atayabilirsiniz. Bir nesneye yapılan tüm referansları silersek, sonsuza dek kaybolur.

Dairesel referanslar

Basit bir karşı örnek bulana kadar bu mantık kulağa harika geliyor: Farz edin ki birbirine referans veren iki nesnemiz var (birbirine referansları saklıyoruz). Başka hiçbir nesne bu nesnelere referans saklamaz.

Bu nesnelere koddan erişilemez, ancak bunlara yine de başvurulur.

Bu nedenle, çöp toplayıcı nesneleri "başvurulan" ve "başvurulanamayan" yerine erişilebilir ve ulaşılamaz olarak ayırır.

Ulaşılabilir nesneler

Öncelikle %100 canlı olan nesneler erişilebilirler listesine eklenir. Örneğin, geçerli iş parçacığı ( Thread.current()) veya konsol InputStream ( System.in).

Ardından erişilebilir nesnelerin listesi, başlangıçtaki erişilebilir nesneler kümesi tarafından başvurulan nesneleri içerecek şekilde genişler. Ardından, bu genişletilmiş küme tarafından başvurulan nesneleri içerecek şekilde yeniden genişletilir ve bu böyle devam eder.

Yani sadece birbirine atıfta bulunan bazı nesneler varsa ve bunlara erişilebilir nesnelerden ulaşmanın bir yolu yoksa, o nesneler çöp olarak kabul edilecek ve silinecektir.


3. Çöp toplama

Bellek parçalanması

Nesne silme ile ilgili bir diğer önemli nokta da bellek parçalanmasıdır. Sürekli olarak nesneler oluşturur ve silerseniz, kısa süre sonra bellek büyük ölçüde parçalanır: dolu bellek alanları, boş bellek alanlarıyla serpiştirilir.

Sonuç olarak, büyük bir boş bellek parçası olmadığı için büyük bir nesneyi (örneğin, milyon öğeli bir dizi) oluşturamayacağımız bir duruma kolayca girebiliriz. Başka bir deyişle, boş bellek olabilir, hatta çoğu olabilir, ancak büyük bir bitişik boş bellek bloğu olmayabilir.

Bellek optimizasyonu (birleştirme)

Java makinesi bu sorunu belirli bir şekilde çözer. Şuna benzer:

Hafıza ikiye ayrılır. Tüm nesneler, belleğin yalnızca yarısında oluşturulur (ve silinir). Hafızadaki boşlukları temizleme zamanı geldiğinde, ilk yarıdaki tüm nesneler ikinci yarıya kopyalanır. Ancak delik olmaması için yan yana kopyalanırlar.

İşlem kabaca şöyle görünür:

1. Adım: Nesneleri oluşturduktan sonra

Java'da çöp toplama

Adım 2: "deliklerin" görünümü

Java 2'de çöp toplama

3. Adım: "deliklerin" ortadan kaldırılması

Java 3'te çöp toplama

İşte bu yüzden nesneleri silmenize gerek yok. Java makinesi, erişilebilir tüm nesneleri yeni bir konuma kopyalar ve nesnelerin saklandığı tüm bellek alanını boşaltır.