30 Mayıs 2011 Pazartesi

Apache Commons Lang Kütüphanesi-2: lang.builder.* Paketi

Lang kütüphanesini incelemeye org.apache.commons.lang.builder paketi ile devam ediyoruz.

Bu pakette kendi sınıflarınız için benzersiz olarak oluşturmanız gereken equals, toString, hashCode, ve compareTo metotlarını daha kolay üretebilmeniz için yardımcı birkaç sınıf bulunur. Şimdi bütün kayda değer metotların kullanıldığı bir örnek görelim ve hepsini teker teker açıklayalım:

import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

public class BuilderTrial {
    private String name;
    private int age;

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

    public static void main(String[] args) {
        //Birkaç nesne oluşturalım.
        BuilderTrial one = new BuilderTrial("Becker", 35);
        BuilderTrial two = new BuilderTrial("Becker", 35);
        BuilderTrial three = new BuilderTrial("Agassi", 33);

        //one ve two farklı nesnelerde aynı verileri tutuyor.
        //three nesnesi ise farklı veri barındırıyor.
        System.out.println("One>>>" + one);
        System.out.println("Two>>>" + two);
        System.out.println("Three>>>" + three);

        System.out.println("one equals two? " + one.equals(two));
        System.out.println("one equals three? " + one.equals(three));

        //one ve two aynı verileri barındırdığı için, aynı hashcode dönülür.
        System.out.println("One HashCode>>> " + one.hashCode());
        System.out.println("Two HashCode>>> " + two.hashCode());
        System.out.println("Three HashCode>>> " + three.hashCode());
    }

    public boolean equals(Object objCompared) {
        if (!(objCompared instanceof BuilderTrial)) {
            return false;
        }

        BuilderTrial rhs = (BuilderTrial) objCompared;

        return new EqualsBuilder().append(name, rhs.name).append(age, rhs.age)
                                  .isEquals();
    }

    public String toString() {
        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append("Name",
            name).append("Age", age).toString();
    }

     public int compareTo(Object o) {
     BuilderTrial builderTrial = (BuilderTrial ) o;
     return new CompareToBuilder()
       .appendSuper(super.compareTo(o)
       .append(this.name, builderTrial.name)
       .append(this.age,  builderTrial.age)
       .toComparison();
    }

    public int hashCode() {
        return new HashCodeBuilder(15, 19).append(name).append(age).toHashCode();
    }
}


Çıktısı:
One>>>BuilderTrial@5[
  Name=Becker
  Age=35
]
Two>>>BuilderTrial@6[
  Name=Becker
  Age=35
]
Three>>>BuilderTrial@7[
  Name=Agassi
  Age=33
]
one equals two? true
one equals three? false
One HashCode>>> -923455822
Two HashCode>>> -923455822
Three HashCode>>> -1433293806


Bir sınıf için equals metodu yazmak, eğer çok fazla üyesi varsa, sayısız if ile boğuşmanızı gerektirebilir. EqualsBuilder sınıfı bu iş için size daha kolay bir yol sunar. Örneğini yukarıda da gördüğünüz gibi, tek yapmanız gereken EqualsBuilder'ın bir örneğinin oluşturup, bu nesne üzerinde, eşitlik kontrolü yapacağınız her alan için append() metodunu çağırmaktır. Tabi en son olarak da isEquals() metounu çağırmayı unutmayın.


ToStringBuilder sınfı toString() metodunun daha anlamlı ve okunabilir çıktılar üretmesini sağlamak için kullanılır. EqualsBuilder sınıfına benzer şekilde, ToStringBuilder'ın bir örneğini oluşturup, üretilecek çıktının biçimini belirtip sonra toString() metodunda olmasını istediğiniz detayları append() ile eklemeniz kafidir. Yine en son toString() metodunu çağırmayı unutmayın tabi.

ToStringBuilder'ı kullanırken çıktı biçimini belirtmek zorunlu değildir. Belirtilmezse DEFAULT_STYLE kullanılır. Diğer biçimler de şunlardır: MULTI_LINE_STYLE, NO_FIELD_NAMES_STYLE, SHORT_PREFIX_STYLE, SIMPLE_STYLE.

Eğer kendi çıktı biçiminizi tanımlamak isterseniz StandartToStringStyle sınıfını genişletebilirsiniz(extend).


HashCodeBuilder sınıfı hashCode() metodunu daha pratik yoldan üretmek için tasarlanmıştır. Diğer xxxBuilder sınıflarından farklı olarak, HashCodeBuilde'ın örneğini oluştururken, iki tane rastgele seçilmiş tek ve sıfırdan farklı sayı belirtirsiniz. Asal sayı kullanmanız tavsiye edilir! Sonra öncekiler gibi append() ile hashcode'da olmasını istediğiniz alanları ekler, toHashCode() ile hashcode'u oluşturursunuz.

HashCodeBuilde, EqualsBuilder ile ortak çalışır. Yani "equals() metodu true dönen iki nesne için hashcode'lar eşit olmalıdır" kuralına uyar.


CompareToBuilder da neredeyse aynıdır. Argüman olan Object referansını uygun tipe dönüştürdükten(cast) sonra CompareToBuilder'ın bir örneğini oluşturup, karşılaştırmak istediğiniz alanları append() ile ekleyip, sonra toComparison() metodunu çağırarak karşılaştırma işlemini gerçekleştirebilirsiniz. append() için sadece çalıştığınız sınıfın alanları ile sınırlı olmadığınıza dikkat edin. Örneğin biz burada appendSuper() ile bir üst sınıfın compareTo() metodunu da hesaplamamıza kattık.


Hepsinin Kısayolu
Bütün bu anlattığımız örneklerin Java Reflection API kullanan bariz bir şekilde daha kısa bir yolu var.

public boolean equals(Object obj) {
    return EqualsBuilder.reflectionEquals(this, obj);
}
public String toString() {
    return ToStringBuilder.reflectionToString(this
           , ToStringStyle.MULTI_LINE_STYLE);
}

public int hashCode() {
    return HashCodeBuilder.reflectionHashCode(this);
}

public int compareTo(Object o) {
   return CompareToBuilder.reflectionCompare(this, o);
}

Bu örneklerdeki kodda neredeyse herşey otomatikleştirilmiştir. Metodların içindeki tek satırlık kodlar, Java'nın Reflection özelliklerini kullanarak, ilgili sınıfın bütün alanlarına erişir ve karşılaştırma ve hesaplama işlemlerini bizim müdahalemize gerek kalmadan gerçekleştirir. Ancak bu yaklaşımın bir eksi yanı vardır. Diğer yönteme göre bariz şekilde yavaştır ve oluşturulan kod üzerinde çok daha az kontrolümüz vardır.

Kolay Gelsin.

Hiç yorum yok:

Yorum Gönder