20 Ağustos 2021 Cuma

Java Object Sınıfı ve Metodları - wikibooks.org çevirisi

 

Java Programming/API/java.lang.Object



java.lang.Object


Object sınıfı, tüm Java sınıflarının üst sınıfıdır. Bu sınıftan tüm Java sınıfları miras alınır. Bu, tüm Java sınıflarında mevcut olan metodlara sahip olmamızı mümkün kılar. Bu, durumun söz konusu olmadığı 
C ++ ile karşılaştırıldığında işleri basitleştirir.

Object sınıfı metodları ve açıklamaları

boolean equals( Object o ); :  Nesneleri karşılaştırmak için genel bir yol sağlar

Class getClass();             :  Class sınıfı bize nesne hakkında daha fazla bilgi verir

int hashCode();                  :  Bir koleksiyondaki nesneleri aramak için kullanılan bir hash değeri döndürür

void notify();                      :  synchronizing thread'lerde kullanılır

void notifyAll();                 :  synchronizing thread'lerde kullanılır

String toString();                :  Nesneyi String'e dönüştürmek için kullanılabilir

void wait();                         :  synchronizing thread'lerde kullanılır

protected Object clone() throws CloneNotSupportedException ; : Mevcut nesneyle tamamen aynı olan yeni bir nesne döndür.

protected void finalize() throws Throwable; : Bu metod garbage collection nesneyi toplamadan hemen önce çalışır.

equals() Metodu


Boolean equals (Object o) yöntemi, nesneleri eşitlik açısından karşılaştırmak için genel bir yol sağlar. Sınıfınızda onu override etmeniz gerekir. O zaman şu şekilde yazabilirsiniz:
  public boolean isCustomerExist( Customer newCustomer )
{
   boolean isRet = false;
   Iterator iter = _collAllCustomer.iterator();
   while ( iter.hasNext() )
   {
      if ( newCustomer.equals( (Customer) iter.next() )
      {
         // -- Customer was found ---
         isRet = true;
      }
   }
  return isRet;
}
  
  
equals() öğesini geçersiz kıldığınızda, her zaman hashCode() öğesini de geçersiz kılmanız gerektiğini unutmayın, böylece iki yöntem tutarlı olur. İki nesne eşitse, aynı hashcode'a sahip olmaları gerekir.

hashCode() Metodu


Çoğu durumda, bu yöntemin varsayılan uygulaması nesne için benzersiz bir sayı döndürdüğünden, bu yöntemi geçersiz kılmamalısınız. Sayı, nesne bir koleksiyona konulduğunda kullanılır. Büyük bir koleksiyonda bir nesneyi bulmak, nesneler tek tek sırayla karşılaştırılırsa biraz zaman alabilir. Aramayı hızlandırmak için, nesneler bir tamsayı karma kod ile ağırlıklandırılan bir ağaç yapısına yerleştirilebilir. Ağaçta gezinirken karma kodu karşılaştırarak, nesne karşılaştırma sayısı azaltılabilir.

   _______ A _____
   |              |  
__ B__          __C__
|     |        |     |
D     E        F     G
...  ...      ...   ...
Size nasıl çalıştığı hakkında genel bir fikir vermek için yukarıdaki şemaya bakın. G nesnesini aradığımızı varsayalım. Ağacın her bir 'düğümünde' hangi yöne gideceğimize karar verebilirsek, 3 adımda G nesnesine ulaşırız.

Doğrusal bir aramada yorumla:

A --- B  ----- C  ---- C  ---- D  ---- E ---- F ---- G
G nesnesine ulaşmak için 8 adıma ihtiyacımız var.

Böylece ağaç yapısı ile arama daha hızlı olacaktır. Ancak yeni bir nesne eklemek daha yavaş olacaktır çünkü ağaç yapısının korunması gerekir. Yeni nesnenin ağaçtaki yeri ilk önce bulunmalıdır.

getClass() Metodu

Programınızdaki her sınıf için bir Class nesnesi vardır. Her dizi, aynı öğe türüne ve boyut sayısına sahip tüm diziler tarafından paylaşılan bir Class nesnesi olarak yansıtılan bir sınıfa da aittir. İlkel Java türleri (boolean, byte, char, short, int, long, float ve double) ve void anahtar sözcüğü de Class nesneleri olarak temsil edilir. Class'ın genel kurucusu yoktur. Bunun yerine Class nesneleri, sınıflar yüklenirken Java Sanal Makinesi tarafından otomatik olarak oluşturulur.

Class'ın en popüler kullanımı, çalışma zamanı sırasında nesnenin sınıf adını bulmaktır.
  ,
  import com.yourCompany.Customer;
...
Object obj = new Customer();
...
System.out.println( "Name:" + obj.getClass().getName() );
  
 

toString() Metodu


Bu yöntem, bir nesneyi bir String'e dönüştürmek için kullanılabilir. Nesneleri String'e dönüştürmek için birçok yerde otomatik olarak kullanılır; örneğin: PrintStream'de, StringBuffer'da ve nesnelerde kullanıldığında string concatenation operatörü için.

Varsayılan uygulama, sınıf adı ve hash kodu ile garip bir dize döndürür.

Örneğin:


  
  String str = "This customer is " + objCust;
  
ToString () yöntemi objCust nesnesinde çağrılır. ToString () yöntemi, debugging için de kullanılabilir:
  
  public class Customer
{
   private String _name;
   private String _address;
   private String _age;
...
   public String toString()
   {
       StringBuffer buf = new StringBuffer();
       buf.append( "Name   = " );  buf.append( _name );     buf.append( "\n" );
       buf.append( "Address= " );  buf.append( _address );  buf.append( "\n" );
       buf.append( "Age    = " );  buf.append( _age );      buf.append( "\n" );
    ...
       return buf.toString();
   }
...
}
  
Bundan sonra, kodunuzda ne zaman bir müşteri nesnesinin ne olduğunu görmek istersiniz, sadece şunu kullanabilirsiniz:
  
  System.out.println( objCustomer );
  

Synchronizing Thread'lerin Metodları


Çok iş parçacıklı bir ortamda, birden fazla iş parçacığı bir kaynağa erişip değiştirebildiğinde, sonuç tahmin edilemez olabilir. Örneğin, birden fazla iş parçacığı tarafından artırılan bir sayaç değişkenimiz olsun.

Dikkat! Senkronizasyon belirsiz bir terimdir. Aynı kod bölümünü aynı anda yürüten tüm iş parçacıklarını yapmaktan ibaret değildir. Tam tersi. Herhangi iki iş parçacığının aynı kod bölümünü aynı anda yürütmesini engeller. Bir işlemin sonunu ikinci bir işlemin başlangıcıyla senkronize eder.





Yukarıdaki kod, aşağıdaki alt işlemlerle oluşturulmuştur:

Read; değişken sayacını oku
Add; değere 1 ekle
Save ; yeni değeri değişken sayaca kaydet
Diyelim ki iki iş parçacığının bu kodu çalıştırması gerekiyor ve eğer sayaç değişkeninin başlangıç değeri sıfır ise, işlemlerden sonra değerin 2 olmasını bekliyoruz.


Yukarıdaki durumda Thread 1 işlemi kaybolur, çünkü Thread 2 kendi değerinin üzerine yazar. Thread 2'nin, Thread 1 işlemi bitirene kadar beklemesini istiyoruz. Aşağıya bakınız:



Kritik Bölüm (Critical Section)
Yukarıdaki örnekte, sayaç+=1 kodu herhangi bir zamanda bir ve yalnızca bir iş parçacığı tarafından yürütülmelidir. Buna kritik bölüm denir. Programlama sırasında, çok iş parçacıklı bir ortamda, kritik bir bölüme ait olan tüm kod parçalarını tanımlamalı ve herhangi bir zamanda yalnızca bir iş parçacığının bu kodları çalıştırabildiğinden emin olmalıyız. Buna senkronizasyon denir.

Konuları senkronize etme (Synchronizing threads)
Kritik bir bölüm koduna iş parçacığı erişimi, iş parçacıkları arasında senkronize edilmelidir, yani herhangi bir zamanda yalnızca bir iş parçacığının onu çalıştırabilmesini sağlamak için.

Nesne monitörü (Object monitor)
Her nesnenin bir Nesne monitörü vardır. Temel olarak, bir iş parçacığı tarafından kritik bir bölüm kodunun yürütülüp yürütülmediğini gösteren bir semafordur. Kritik bir bölümün yürütülebilmesi için iş parçacığının bir Nesne izleyicisi edinmesi gerekir. Bir seferde yalnızca bir iş parçacığı o nesnenin monitörüne sahip olabilir.


Bir iş parçacığı, üç yoldan biriyle nesnenin monitörünün sahibi olur

Bu nesnenin synchronized instance method yürüterek. Senkronize edilmiş anahtar kelimeye bakın.

Nesne üzerinde senkronize olan synchronized statement gövdesini yürüterek. Senkronize edilmiş anahtar kelimeye bakın.

Class türündeki nesneler için, o sınıfın synchronized static method yürüterek.

Object Monitor senkronizasyonla ilgilenir, öyleyse neden "wait() ve notify() yöntemlerine" ihtiyacımız var?

Senkronizasyon için onlara gerçekten ihtiyacımız yok, ancak bazı durumlarda bunları kullanmak güzel. Güzel ve düşünceli bir thread onları kullanacaktır. Kritik bir bölümün yürütülmesi sırasında iş parçacığı sıkışmış olabilir, devam edemeyebilir. Bir IO ve diğer kaynakları beklediği için olabilir. Her durumda, iş parçacığının nispeten uzun bir süre beklemesi gerekebilir. İş parçacığının nesne monitörüne tutunması ve diğer iş parçacıklarının işini yapmasını engellemesi bencillik olurdu. Böylece iş parçacığı, nesne üzerinde wait() yöntemini çağırarak bir 'bekleme' durumuna gider. İş parçacığının nesne monitörünü aldığı aynı nesne olmalıdır.
Öte yandan, bir iş parçacığı, yalnızca, kaynak kullanılabilir olduğunda notify() yöntemini çağıracak en az bir başka iş parçacığı varsa, wait() yöntemini çağırmalıdır, aksi takdirde iş parçacığı, bir parametre olarak zaman aralığı belirtilir.
Bir benzetme yapalım. Bazı eşyaları almak için bir dükkana girersiniz. Tezgahta sıraya girersiniz, satış memurunun dikkatini çekersiniz - onun "nesne-monitörünü" alırsınız. İstediğiniz ürünü soruyorsunuz. Bir depodan bir ürün getirilmesi gerekiyor. Beş dakikadan fazla sürecektir, bu nedenle satış memurunu serbest bırakırsınız ("nesne monitörünü" ona geri verin), böylece diğer müşterilere hizmet verebilir. Bekleme durumuna geçersiniz. Diyelim ki bekleyen beş müşteri daha var. Depodan eşyaları getiren başka bir satış memuru var. Bunu yaparken, ilk satış memurunun dikkatini çeker, nesne monitörünü alır ve bekleyen bir veya tüm müşteriyi/müşterileri bilgilendirir, böylece bekleyen müşteri(ler) uyanır ve müşterinin dikkatini çekmek için tekrar sıraya girer. ilk satış memuru.
Bekleyen müşteri ile ürünleri getiren satış memuru arasındaki senkronizasyona dikkat edin. Bu bir tür üretici-tüketici senkronizasyonudur.
Ayrıca, ilk satış memuruna ait yalnızca bir nesne monitörü olduğunu unutmayın. Beklemeden ve bir bildirimin gerçekleşebilmesi için önce bu nesne-monitörünün/memurun notify edilmesi gerekir.

final void wait() yöntemi
Geçerli iş parçacığı, bu nesnenin monitörüne sahip olmalıdır. İş parçacığı, bu monitörün sahipliğini serbest bırakır ve başka bir iş parçacığı, bu nesnenin monitöründe bekleyen iş parçacıklarının, notify yöntemine veya notifyAll yöntemine yapılan bir çağrı yoluyla uyanmasını bildirene kadar bekler. İş parçacığı daha sonra monitörün sahipliğini yeniden elde edene ve yürütmeye devam edene kadar bekler.
final void wait (long time)
Bekleme ile aynıdır, ancak bir bildirim olup olmadığına bakılmaksızın belirtilen süre geçtikten sonra iş parçacığı uyanır.
final void notify()
Bu yöntem yalnızca bu nesnenin monitörünün sahibi olan bir iş parçacığı tarafından çağrılmalıdır. Bu nesnenin monitöründe bekleyen tek bir iş parçacığını uyandırır. Bu nesnenin monitöründe çok sayıda iş parçacığı bekliyorsa, bunlardan biri uyandırılmak üzere seçilir. Seçim keyfidir ve uygulamanın takdirine bağlı olarak gerçekleşir. Bir iş parçacığı, bekleme yöntemlerinden birini çağırarak bir nesnenin monitöründe bekler.
Uyandırılan iş parçacığı, mevcut iş parçacığı bu nesne üzerindeki kilidi bırakana kadar ilerleyemeyecektir. Uyandırılan iş parçacığı, bu nesne üzerinde eşzamanlamak için aktif olarak rekabet edebilecek diğer iş parçacıklarıyla olağan şekilde rekabet edecektir; örneğin, uyanmış iş parçacığı, bu nesneyi kilitleyecek bir sonraki iş parçacığı olma konusunda güvenilir bir ayrıcalığa veya dezavantaja sahip değildir.
final void notifyAll()
notify() ile aynıdır, ancak bu nesnenin monitöründe bekleyen tüm iş parçacıklarını uyandırır.

sleep() ve wait() yöntemleri arasındaki farklar nelerdir?
Thread.sleep(milis)
Bu, Thread sınıfının statik bir yöntemidir. Şu anda yürütülmekte olan iş parçacığının belirtilen milisaniye sayısı boyunca uyumasına (yürütmeyi geçici olarak durdurmasına) neden olur. İş parçacığı herhangi bir monitörün sahipliğini kaybetmez. Bu, iş parçacığının bir nesne izleyicisi varsa, bu monitöre ihtiyaç duyan diğer tüm iş parçacıklarının engellendiği anlamına gelir. Bu yöntem, iş parçacığının herhangi bir monitörü olup olmadığına bakılmaksızın çağrılabilir.
wait()
Bu yöntem, Object sınıfından miras alınır. İş parçacığı, wait() yöntemini çağırmadan önce o nesnenin nesne monitörünü almış olmalıdır. Nesne izleyicisi wait() yöntemiyle serbest bırakılır, bu nedenle bu nesne izleyicisini isteyen diğer bekleyen iş parçacıklarını engellemez.



0 yorum: