İki nesnenin derinlemesine karşılaştırmasını yapmak için bir Java yansıtma aracı var mı? [kapalı]


99

clone()Büyük bir proje içinde çeşitli işlemler için birim testleri yazmaya çalışıyorum ve bir yerde aynı türden iki nesneyi alabilen, derin bir karşılaştırma yapabilen ve aynı mı değil mi?


1
Bu sınıf, nesne grafiklerinin belirli bir noktasında aynı nesneleri mi yoksa yalnızca aynı referansları mı kabul edebileceğini nasıl bilecek?
Zed

İdeal olarak, yeterince yapılandırılabilir olacaktır :) Otomatik bir şey arıyorum, böylece yeni alanlar eklenirse (ve klonlanmazsa), test bunları tanımlayabilir.
Uri

3
Söylemeye çalıştığım şey, karşılaştırmaları yine de yapılandırmanız (yani uygulamanız) gerekeceği. Öyleyse neden sınıflarınızdaki eşittir yöntemini geçersiz kılıp bunu kullanmıyorsunuz?
Zed

3
Eşittir, büyük ve karmaşık bir nesne için yanlış döndürürse, nereden başlamalısınız? Nesneyi çok satırlı bir Dize haline getirip bir Dize karşılaştırması yapmaktan çok daha iyi olursunuz. O zaman iki nesnenin tam olarak nerede farklı olduğunu görebilirsiniz. IntelliJ, iki sonuç arasında birden fazla değişikliğin bulunmasına yardımcı olan bir "değişiklikler" karşılaştırma penceresi açar, yani assertEquals (dize1, dize2) çıktısını anlar ve size bir karşılaştırma penceresi verir.
Peter Lawrey

Burada kabul
edilenin

Yanıtlar:


63

Unitils bu işleve sahiptir:

Java varsayılan / boş değerlerini göz ardı etmek ve koleksiyonların sırasını göz ardı etmek gibi farklı seçeneklerle yansıtma yoluyla eşitlik iddiası


10
Bu işlev üzerinde bazı testler yaptım ve EqualsBuilder'ın yapmadığı yerlerde derin bir karşılaştırma yapıyor gibi görünüyor.
Howard Mayıs

Bunun geçici alanları görmezden gelmemesinin bir yolu var mı?
sıkıştırın

@Pinch seni duyuyorum. Derin karşılaştırma aracının unitilstam olarak kusurlu olduğunu söyleyebilirim, çünkü değişkenleri gözlemlenebilir bir etkiye sahip olmasalar bile karşılaştırır . Değişkenleri karşılaştırmanın bir başka (istenmeyen) sonucu, saf kapanışların (kendi durumları olmadan) desteklenmemesidir. Ayrıca, karşılaştırılan nesnelerin aynı çalışma zamanı türünde olmasını gerektirir. Kollarımı sıvadım ve bu endişeleri gideren kendi derin karşılaştırma aracımı yarattım .
beluchin

@Wolfgang bizi yönlendirecek herhangi bir örnek kod var mı? Bu sözü nereden aldınız?
anon58192932

30

Bu soruyu seviyorum! Temel olarak, neredeyse hiç cevaplanmadığı veya kötü yanıtlanmadığı için. Henüz kimse anlamamış gibi. El değmemiş topraklar :)

Öncelikle, kullanmayı düşünmeyin bile equals. equalsJavadoc'ta tanımlandığı gibi sözleşmesi, bir eşitlik ilişkisi değil , bir eşdeğerlik ilişkisidir (dönüşlü, simetrik ve geçişli) . Bunun için de antisimetrik olması gerekir. Bunun tek uygulaması, equalsgerçek bir eşitlik ilişkisidir (veya olabilir) java.lang.Object. equalsGrafikteki her şeyi karşılaştırmak için kullanmış olsanız bile , sözleşmeyi bozma riski oldukça yüksektir. Josh Bloch'un Effective Java'da belirttiği gibi , eşittir sözleşmesini bozmak çok kolaydır:

"Örneklenebilir bir sınıfı genişletmenin ve eşittir sözleşmesini korurken bir özellik eklemenin hiçbir yolu yoktur"

Ayrıca, bir boole yönteminin gerçekten ne faydası var ki? Orijinal ile klon arasındaki tüm farklılıkları özetlemek güzel olurdu, sence de öyle değil mi? Ayrıca, burada grafikteki her nesne için karşılaştırma kodu yazmak / sürdürmekle uğraşmak istemediğinizi, bunun yerine zamanla değiştikçe kaynakla ölçeklenecek bir şey aradığınızı varsayacağım.

Soooo, gerçekten istediğin şey bir tür durum karşılaştırma aracı. Bu aracın nasıl uygulandığı gerçekten alan modelinizin doğasına ve performans kısıtlamalarınıza bağlıdır. Deneyimlerime göre, genel bir sihirli mermi yok. Ve çok sayıda yinelemede yavaş olacaktır . Ancak bir klonlama işleminin bütünlüğünü test etmek için, işi oldukça iyi yapacak. En iyi iki seçeneğiniz serileştirme ve yansıtmadır.

Karşılaşacağınız bazı sorunlar:

  • Koleksiyon sırası: Aynı nesneleri farklı bir sırada tutuyorlarsa, iki koleksiyon benzer mi kabul edilmelidir?
  • Hangi alanlar göz ardı edilecek: Geçici? Statik?
  • Tür eşdeğeri: Alan değerleri tam olarak aynı türde mi olmalı? Yoksa birinin diğerini uzatması uygun mu?
  • Dahası var ama unutuyorum ...

XStream oldukça hızlıdır ve XMLUnit ile birleştirildiğinde, işi sadece birkaç satır kodla yapar. XMLUnit güzeldir çünkü tüm farklılıkları bildirebilir veya bulduğu ilk anda durabilir. Ve çıktısı farklı düğümlere giden xpath'i içerir, ki bu güzeldir. Varsayılan olarak sırasız koleksiyonlara izin vermez, ancak bunu yapacak şekilde yapılandırılabilir. Özel bir fark işleyicisinin enjekte edilmesi (a olarak adlandırılır DifferenceListener), sıralamayı göz ardı etme dahil olmak üzere farklılıkları nasıl ele almak istediğinizi belirlemenize olanak tanır. Ancak, en basit özelleştirmenin ötesinde bir şey yapmak istediğinizde, yazmak zorlaşır ve ayrıntılar belirli bir etki alanı nesnesine bağlanma eğilimindedir.

Benim kişisel tercihim, bildirilen tüm alanlar arasında geçiş yapmak ve her birine derinlemesine inmek için yansımayı kullanmak ve ilerledikçe farklılıkları takip etmektir. Uyarı kelimesi: Yığın taşması istisnalarını sevmediğiniz sürece özyineleme kullanmayın. İşleri bir yığınla kapsam içinde tutun (birLinkedListya da başka birşey). Genellikle geçici ve statik alanları görmezden gelirim ve daha önce karşılaştırdığım nesne çiftlerini atlarım, bu nedenle birisi kendine referanslı kod yazmaya karar verirse sonsuz döngülerle karşılaşmam (Ancak, ne olursa olsun her zaman ilkel sarmalayıcıları karşılaştırırım. , aynı nesne başvuruları sıklıkla yeniden kullanıldığından). Koleksiyon sıralamayı yok saymak ve özel türleri veya alanları yok saymak için işleri önceden yapılandırabilirsiniz, ancak durum karşılaştırma ilkelerimi ek açıklamalar yoluyla alanların kendisinde tanımlamayı seviyorum. Bu, IMHO, çalışma zamanında sınıfla ilgili meta verileri kullanılabilir hale getirmek için ek açıklamaların tam olarak kastedildiği şeydir. Gibi bir şey:


@StatePolicy(unordered=true, ignore=false, exactTypesOnly=true)
private List<StringyThing> _mylist;

Bence bu gerçekten zor bir problem ama tamamen çözülebilir! Ve sizin için çalışan bir şeye sahip olduğunuzda, gerçekten, gerçekten, kullanışlıdır :)

Yani, iyi şanslar. Ve saf dahi olan bir şey bulursanız, paylaşmayı unutmayın!


15

Java-util'de DeepEquals ve DeepHashCode () görün: https://github.com/jdereg/java-util

Bu sınıf, orijinal yazarın istediği şeyi tam olarak yapar.


4
Uyarı: DeepEquals, varsa bir nesnenin .equals () yöntemini kullanır. İstediğin bu olmayabilir.
Adam

4
Bir equals () yöntemi açıkça eklenmişse, bir sınıfta yalnızca .equals () kullanır, aksi takdirde üyelere göre karşılaştırma yapar. Buradaki mantık, eğer birisi özel bir equals () yöntemi yazma çabasına girerse, o zaman bunun kullanılması gerektiğidir. Gelecekteki geliştirme: bayrağın, var olsalar bile equals () yöntemlerini yok saymasına izin verin. Java-util'de CaseInsensitiveMap / Set gibi faydalı araçlar vardır.
John DEREGNAUCOURT

Alanları karşılaştırma konusunda endişeleniyorum. Alanlardaki fark, nesnelerin müşterisinin bakış açısından gözlemlenemeyebilir ve yine de alanlara dayalı derin bir karşılaştırma onu işaretler. Ek olarak, alanların karşılaştırılması, nesnelerin sınırlayıcı olabilen aynı çalışma zamanı türünde olmasını gerektirir.
beluchin

Yukarıdaki @beluchin cevabını vermek için, DeepEquals.deepEquals () her zaman alan alan karşılaştırma yapmaz. Birincisi, eğer varsa (bu Object üzerinde değilse) bir yöntemde .equals () kullanma seçeneğine sahiptir veya yok sayılabilir. İkinci olarak, Haritalar / Koleksiyonları karşılaştırırken, Koleksiyon veya Harita türüne veya Koleksiyon / Harita üzerindeki alanlara bakmaz. Bunun yerine, onları mantıksal olarak karşılaştırır. Bir LinkedHashMap, aynı sırayla aynı içeriğe ve öğelere sahipse, bir TreeMap'e eşit olabilir. Sıralanmamış Koleksiyonlar ve Haritalar için yalnızca boyut ve derin eşittir öğeler gereklidir.
John DeRegnaucourt

Haritalar / Koleksiyonlar karşılaştırılırken, Koleksiyon veya Harita türüne veya Koleksiyon / Harita üzerindeki alanlara bakmaz. Bunun yerine, onları mantıksal olarak @JohnDeRegnaucourt karşılaştırır , bu mantıksal karşılaştırmayı, yani yalnızca publickoleksiyon / haritalara uygulanabilir olmanın aksine, yalnızca tüm türler için geçerli olanı karşılaştırarak tartışırım .
beluchin

10

Eşittir () Yöntemini Geçersiz Kıl

EqualsBuilder.reflectionEquals () öğesini burada açıklandığı gibi kullanarak sınıfın equals () yöntemini geçersiz kılabilirsiniz :

 public boolean equals(Object obj) {
   return EqualsBuilder.reflectionEquals(this, obj);
 }

8

In AssertJ , yapabileceğiniz:

Assertions.assertThat(expectedObject).isEqualToComparingFieldByFieldRecursively(actualObject);

Muhtemelen her durumda işe yaramayacaktır, ancak düşündüğünüz daha fazla durumda işe yarayacaktır.

Belgelerin söylediği şu:

Test edilen nesnenin (gerçek), özellik / alan karşılaştırmasına göre (devralınanlar dahil) özyinelemeli bir özelliğe / alana dayalı olarak verilen nesneye eşit olduğunu iddia edin. Bu, gerçek eşittir uygulaması size uygun değilse yararlı olabilir. Özyinelemeli özellik / alan karşılaştırması, özel eşittir uygulamasına sahip alanlara uygulanmaz, yani alan karşılaştırmasına göre alan yerine geçersiz kılınan eşittir yöntemi kullanılacaktır.

Özyinelemeli karşılaştırma döngüleri işler. Varsayılan olarak kayan değerler 1.0E-6 hassasiyetiyle karşılaştırılır ve 1.0E-15 ile iki katına çıkar.

ComparatorForFields (Comparator, String ...) ve usingComparatorForType (Karşılaştırıcı, Sınıf) kullanarak (iç içe geçmiş) alan başına özel bir karşılaştırıcı veya tür belirtebilirsiniz.

Karşılaştırılacak nesneler farklı türlerde olabilir ancak aynı özelliklere / alanlara sahip olmalıdır. Örneğin, gerçek nesnenin bir String alanı adı varsa, diğer nesnenin de bir tane olması beklenir. Bir nesnenin bir alanı ve aynı ada sahip bir özelliği varsa, özellik değeri alan üzerinde kullanılacaktır.


2
isEqualToComparingFieldByFieldRecursivelyartık kullanımdan kaldırıldı. assertThat(expectedObject).usingRecursiveComparison().isEqualTo(actualObject);
Onun

7

Hibernate Envers tarafından revize edilen iki varlık örneğinin karşılaştırmasını uygulamak zorunda kaldı. Kendi farklılığımı yazmaya başladım ama sonra aşağıdaki çerçeveyi buldum.

https://github.com/SQiShER/java-object-diff

Aynı türden iki nesneyi karşılaştırabilirsiniz ve değişiklikleri, eklemeleri ve çıkarmaları gösterecektir. Değişiklik yoksa, nesneler eşittir (teoride). Kontrol sırasında göz ardı edilmesi gereken alıcılar için ek açıklamalar sağlanır. Çerçeve çalışması, eşitlik kontrolünden çok daha geniş uygulamalara sahiptir, yani bir değişiklik günlüğü oluşturmak için kullanıyorum.

Performansı iyi, JPA varlıklarını karşılaştırırken, önce onları varlık yöneticisinden ayırdığınızdan emin olun.


6

XStream kullanıyorum:

/**
 * @see java.lang.Object#equals(java.lang.Object)
 */
@Override
public boolean equals(Object o) {
    XStream xstream = new XStream();
    String oxml = xstream.toXML(o);
    String myxml = xstream.toXML(this);

    return myxml.equals(oxml);
}

/**
 * @see java.lang.Object#hashCode()
 */
@Override
public int hashCode() {
    XStream xstream = new XStream();
    String myxml = xstream.toXML(this);
    return myxml.hashCode();
}

5
Listelerden başka koleksiyonlar, öğeleri farklı sırayla döndürebilir, bu nedenle dize karşılaştırması başarısız olur.
Alexey Berezkin

Ayrıca serileştirilemeyen sınıflar başarısız olur
Zwelch

5

http://www.unitils.org/tutorial-reflectionassert.html

public class User {

    private long id;
    private String first;
    private String last;

    public User(long id, String first, String last) {
        this.id = id;
        this.first = first;
        this.last = last;
    }
}
User user1 = new User(1, "John", "Doe");
User user2 = new User(1, "John", "Doe");
assertReflectionEquals(user1, user2);

2
eşitler hakkında herhangi bir etkinizin olmadığı, oluşturulan sınıfları işlemeniz gerekiyorsa özellikle yararlıdır!
Matthias B


1
@ user829755 Bu şekilde puan kaybederim. SO hepsi puan oyunu hakkında)) İnsanlar yapılan iş için kredi almayı sever, ben de öyleyim.
gavenkoa

3

Hamcrest, Matcher ile aynıPropertyValuesAs'a sahiptir . Ancak JavaBeans Sözleşmesine dayanır (alıcılar ve ayarlayıcılar kullanır). Karşılaştırılacak nesnelerin öznitelikleri için alıcıları ve ayarlayıcıları yoksa, bu çalışmayacaktır.

import static org.hamcrest.beans.SamePropertyValuesAs.samePropertyValuesAs;
import static org.junit.Assert.assertThat;

import org.junit.Test;

public class UserTest {

    @Test
    public void asfd() {
        User user1 = new User(1, "John", "Doe");
        User user2 = new User(1, "John", "Doe");
        assertThat(user1, samePropertyValuesAs(user2)); // all good

        user2 = new User(1, "John", "Do");
        assertThat(user1, samePropertyValuesAs(user2)); // will fail
    }
}

Kullanıcı fasulyesi - alıcılar ve ayarlayıcılarla

public class User {

    private long id;
    private String first;
    private String last;

    public User(long id, String first, String last) {
        this.id = id;
        this.first = first;
        this.last = last;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getFirst() {
        return first;
    }

    public void setFirst(String first) {
        this.first = first;
    }

    public String getLast() {
        return last;
    }

    public void setLast(String last) {
        this.last = last;
    }

}

Bu isFoo, bir Booleanözellik için okuma yöntemi kullanan bir POJO'nuz olana kadar harika çalışır . Düzeltmek için 2016'dan beri açık olan bir PR var. github.com/hamcrest/JavaHamcrest/pull/136
Snekse

2

Nesneleriniz Serializable uyguluyorsa, bunu kullanabilirsiniz:

public static boolean deepCompare(Object o1, Object o2) {
    try {
        ByteArrayOutputStream baos1 = new ByteArrayOutputStream();
        ObjectOutputStream oos1 = new ObjectOutputStream(baos1);
        oos1.writeObject(o1);
        oos1.close();

        ByteArrayOutputStream baos2 = new ByteArrayOutputStream();
        ObjectOutputStream oos2 = new ObjectOutputStream(baos2);
        oos2.writeObject(o2);
        oos2.close();

        return Arrays.equals(baos1.toByteArray(), baos2.toByteArray());
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

1

Bağlantılı Liste örneğinizin işlenmesi o kadar da zor değil. Kod iki nesne grafiğini geçerken, ziyaret edilen nesneleri bir Set veya Haritaya yerleştirir. Başka bir nesne referansına geçmeden önce, bu küme nesnenin halihazırda geçiş yapılıp yapılmadığını görmek için test edilir. Eğer öyleyse, daha ileri gitmeye gerek yok.

LinkedList (Yığın gibi, ancak üzerinde senkronize yöntemler olmadan, bu yüzden daha hızlı) diyen yukarıdaki kişiye katılıyorum. Her alanı elde etmek için yansıma kullanırken bir Yığın kullanarak nesne grafiğini geçmek ideal çözümdür. Bir kez yazıldığında, bu "harici" eşittir () ve "harici" hashCode (), tüm equals () ve hashCode () yöntemlerinin çağırması gereken şeydir. Bir daha asla bir customer equals () yöntemine ihtiyacınız yok.

Google Code'da listelenen, eksiksiz bir nesne grafiğinden geçen bir miktar kod yazdım. Json-io (http://code.google.com/p/json-io/) sayfasına bakın. Bir Java nesne grafiğini JSON'a serileştirir ve ondan seri durumdan çıkarılır. Genel kurucular olsun veya olmasın, Serialize edilebilir veya Serialize edilemeyen, vb. Tüm Java nesnelerini işler. Bu aynı geçiş kodu, harici "equals ()" ve harici "hashcode ()" uygulamasının temelini oluşturacaktır. Btw, JsonReader / JsonWriter (json-io) genellikle yerleşik ObjectInputStream / ObjectOutputStream'den daha hızlıdır.

Bu JsonReader / JsonWriter karşılaştırma için kullanılabilir, ancak hashcode ile yardımcı olmayacaktır. Evrensel bir hashcode () ve equals () istiyorsanız, kendi koduna ihtiyacı vardır. Bunu genel bir grafik ziyaretçisiyle başarabilirim. Göreceğiz.

Diğer hususlar - statik alanlar - bu kolaydır - bunlar atlanabilir çünkü tüm equals () örnekleri statik alanlar için aynı değere sahip olacaktır çünkü statik alanlar tüm örneklerde paylaşılır.

Geçici alanlara gelince - bu seçilebilir bir seçenek olacaktır. Bazen geçici olayların diğer zamanları saymamasını isteyebilirsiniz. "Bazen deli gibi hissediyorsun, bazen hissetmiyorsun."

Json-io projesine tekrar bakın (diğer projelerim için) ve harici eşittir () / hashcode () projesini bulacaksınız. Henüz bir ismim yok ama belli olacak.


0

Sanırım bunu biliyorsunuz, ama teoride, iki nesnenin gerçekten eşit olduğunu iddia etmek için her zaman .equals değerini geçersiz kılmanız gerekiyor. Bu, üyelerinde geçersiz kılınan .equals yöntemlerini kontrol ettikleri anlamına gelir.

Bu tür şeyler neden .equals nesnesinde tanımlanır.

Bu tutarlı bir şekilde yapılsaydı bir sorun yaşamazdınız.


2
Sorun şu ki, bunu yazmadığım büyük bir mevcut kod tabanı için test etmeyi otomatikleştirmek istiyorum ... :)
Uri,

0

Böylesine derin bir karşılaştırma için durdurma garantisi sorun olabilir. Aşağıdakiler ne yapmalı? (Böyle bir karşılaştırıcı uygularsanız, bu iyi bir birim testi olur.)

LinkedListNode a = new LinkedListNode();
a.next = a;
LinkedListNode b = new LinkedListNode();
b.next = b;

System.out.println(DeepCompare(a, b));

İşte bir tane daha:

LinkedListNode c = new LinkedListNode();
LinkedListNode d = new LinkedListNode();
c.next = d;
d.next = c;

System.out.println(DeepCompare(c, d));

Yeni bir sorunuz varsa, lütfen Soru Sor düğmesine tıklayarak sorun . Bağlam sağlamaya yardımcı oluyorsa bu soruya bir bağlantı ekleyin.
YoungHobbit

@younghobbit: hayır bu yeni bir soru değil. Bir yanıttaki soru işareti, bu bayrağı uygun yapmaz. Lütfen daha dikkatli olun.
Ben Voigt

Bundan: Using an answer instead of a comment to get a longer limit and better formatting.Eğer bu bir yorumsa, neden cevap bölümünü kullanalım? Bu yüzden işaretledim. yüzünden değil ?. Bu cevap, yorumu geride bırakmayan başka biri tarafından zaten işaretlendi. Bunu inceleme kuyruğuna yeni aldım. Benim hatam olabilir, daha dikkatli olmalıydım.
YoungHobbit

0

Ray Hulha çözümünden esinlenilen en kolay çözümün nesneyi seri hale getirmek ve ardından ham sonucu derinlemesine karşılaştırmak olduğunu düşünüyorum.

Serileştirme bayt, json, xml veya basit toString vb. Olabilir. ToString daha ucuz görünüyor. Lombok, bizim için ücretsiz, kolay özelleştirilebilir ToSTring üretir. Aşağıdaki örneğe bakın.

@ToString @Getter @Setter
class foo{
    boolean foo1;
    String  foo2;        
    public boolean deepCompare(Object other) { //for cohesiveness
        return other != null && this.toString().equals(other.toString());
    }
}   

0

Apache size bir şey verir, her iki nesneyi de dizeye dönüştürün ve dizeleri karşılaştırın, ancak toString () 'i Geçersiz Kılmalısınız

obj1.toString().equals(obj2.toString())

ToString () geçersiz kıl

Tüm alanlar ilkel türlerse:

import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
@Override
public String toString() {return 
ReflectionToStringBuilder.toString(this);}

İlkel olmayan alanlarınız ve / veya koleksiyonunuz ve / veya haritanız varsa:

// Within class
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
@Override
public String toString() {return 
ReflectionToStringBuilder.toString(this,new 
MultipleRecursiveToStringStyle());}

// New class extended from Apache ToStringStyle
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.util.*;

public class MultipleRecursiveToStringStyle extends ToStringStyle {
private static final int    INFINITE_DEPTH  = -1;

private int                 maxDepth;

private int                 depth;

public MultipleRecursiveToStringStyle() {
    this(INFINITE_DEPTH);
}

public MultipleRecursiveToStringStyle(int maxDepth) {
    setUseShortClassName(true);
    setUseIdentityHashCode(false);

    this.maxDepth = maxDepth;
}

@Override
protected void appendDetail(StringBuffer buffer, String fieldName, Object value) {
    if (value.getClass().getName().startsWith("java.lang.")
            || (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
        buffer.append(value);
    } else {
        depth++;
        buffer.append(ReflectionToStringBuilder.toString(value, this));
        depth--;
    }
}

@Override
protected void appendDetail(StringBuffer buffer, String fieldName, 
Collection<?> coll) {
    for(Object value: coll){
        if (value.getClass().getName().startsWith("java.lang.")
                || (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
            buffer.append(value);
        } else {
            depth++;
            buffer.append(ReflectionToStringBuilder.toString(value, this));
            depth--;
        }
    }
}

@Override
protected void appendDetail(StringBuffer buffer, String fieldName, Map<?, ?> map) {
    for(Map.Entry<?,?> kvEntry: map.entrySet()){
        Object value = kvEntry.getKey();
        if (value.getClass().getName().startsWith("java.lang.")
                || (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
            buffer.append(value);
        } else {
            depth++;
            buffer.append(ReflectionToStringBuilder.toString(value, this));
            depth--;
        }
        value = kvEntry.getValue();
        if (value.getClass().getName().startsWith("java.lang.")
                || (maxDepth != INFINITE_DEPTH && depth >= maxDepth)) {
            buffer.append(value);
        } else {
            depth++;
            buffer.append(ReflectionToStringBuilder.toString(value, this));
            depth--;
        }
    }
}}

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.