2009-10-06 9 views
50

Mam klasy z informacji o osobie, która wygląda mniej więcej tak:Druk wszystkie zmienne wartość z klasy

public class Contact { 
    private String name; 
    private String location; 
    private String address; 
    private String email; 
    private String phone; 
    private String fax; 

    public String toString() { 
     // Something here 
    } 
    // Getters and setters. 
} 

chcę toString() wrócić this.name +" - "+ this.locations + ... dla wszystkich zmiennych. Próbowałem zaimplementować go za pomocą refleksji, jak pokazano z this question, ale nie mogę drukować zmiennych instancji.

Jaki jest właściwy sposób rozwiązania tego problemu?

+0

Co się stało, gdy próbowałeś to zrobić z odbiciem? To działa dla mnie ... – CPerkins

+0

Nie wiedziałem, co przekazać do field.get(). Po przeczytaniu odpowiedzi płodu uczę się, że "to" powinno zostać przekazane. – Macarse

+0

Możliwy duplikat [Dumping właściwości obiektu java] (http://stackoverflow.com/questions/603013/dumping-a-java-objects-properties) –

Odpowiedz

73

Od Implementing toString:

public String toString() { 
    StringBuilder result = new StringBuilder(); 
    String newLine = System.getProperty("line.separator"); 

    result.append(this.getClass().getName()); 
    result.append(" Object {"); 
    result.append(newLine); 

    //determine fields declared in this class only (no fields of superclass) 
    Field[] fields = this.getClass().getDeclaredFields(); 

    //print field names paired with their values 
    for (Field field : fields ) { 
    result.append(" "); 
    try { 
     result.append(field.getName()); 
     result.append(": "); 
     //requires access to private field: 
     result.append(field.get(this)); 
    } catch (IllegalAccessException ex) { 
     System.out.println(ex); 
    } 
    result.append(newLine); 
    } 
    result.append("}"); 

    return result.toString(); 
} 
+11

Czyste wdrożenie tego jest dostępne w programie commons-lang ['ReflectionToStringBuilder'] (http://commons.apache.org/lang/api-release/org/apache/commons/lang3/builder/ReflectionToStringBuilder.html) –

+5

@ SivakumarK link jest zepsuty użyj: http://commons.apache.org/ proper/commons-lang/apidocs/org/apache/commons/lang3/builder/ReflectionToStringBuilder.html zamiast tego – Kuchi

+0

@kuchi zaktualizowali go do wersji 3.1, zmieniając go w podanym adresie URL, który sprawi, że zadziała –

7

Podczas uzyskiwania dostępu do wartości pola należy przekazać instancję zamiast wartości NULL.

Dlaczego nie używać tutaj generowania kodu? Na przykład Eclipse wygeneruje dla ciebie poprawną implementację toString.

32

Dlaczego chcesz wyważać otwartych drzwi, gdy istnieją opensource, które są już robi zadanie dość ładnie.

Zarówno apache common-langs i spring wsparcie niektóre bardzo elastyczny budowniczy

dla Apache, oto jak to zrobić refleksyjnie

@Override 
public String toString() 
{ 
    return ToStringBuilder.reflectionToString(this); 
} 

Oto jak to zrobić, jeśli tylko chcesz wydrukować pola, które troszczysz się o.

@Override 
public String toString() 
{ 
    return new ToStringBuilder(this) 
     .append("name", name) 
     .append("location", location) 
     .append("address", address) 
     .toString(); 
} 

Możesz iść tak daleko, jak „stylizacji” swojej wydruków z non-default ToStringStyle lub nawet dostosowując ją swoim własnym stylu.

Nie osobiście wypróbowałem api wiosna ToStringCreator, ale wygląda bardzo podobnie.

+0

Pierwsza sprężyna jest kulawa, po prostu ją styluje, nie ma tam refleksji –

8

Generic toString() jedno-liner, wykorzystując odbicie styl i dostosowanie:

import org.apache.commons.lang3.builder.ReflectionToStringBuilder; 
import org.apache.commons.lang3.builder.ToStringStyle; 
... 
public String toString() 
{ 
    return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE); 
} 
+0

to nie działa dla mnie. Moja klasa ma prywatne zmienne i metody pobierania –

22

Jeśli używasz Eclipse, to powinno być łatwe:

1.Press Alt + Przesunięcie + S

2.Choose "Generowanie toString() ..."

Ciesz się! Możesz mieć dowolny szablon toString().

Działa to również z programami pobierającymi/ustawiającymi.

0

Dodatek z odpowiedzią @let, musisz pobrać wszystkie pola modelu (górna hierarchia) i ustawić field.setAccessible(true), aby uzyskać dostęp do prywatnych członków. Oto pełna urywek:

@Override 
public String toString() { 
    StringBuilder result = new StringBuilder(); 
    String newLine = System.getProperty("line.separator"); 

    result.append(getClass().getSimpleName()); 
    result.append(" {"); 
    result.append(newLine); 

    List<Field> fields = getAllModelFields(getClass()); 

    for (Field field : fields) { 
     result.append(" "); 
     try { 
      result.append(field.getName()); 
      result.append(": "); 
      field.setAccessible(true); 
      result.append(field.get(this)); 

     } catch (IllegalAccessException ex) { 
//    System.err.println(ex); 
     } 
     result.append(newLine); 
    } 
    result.append("}"); 
    result.append(newLine); 

    return result.toString(); 
} 

private List<Field> getAllModelFields(Class aClass) { 
    List<Field> fields = new ArrayList<>(); 
    do { 
     Collections.addAll(fields, aClass.getDeclaredFields()); 
     aClass = aClass.getSuperclass(); 
    } while (aClass != null); 
    return fields; 
} 
2

Innym prostym rozwiązaniem jest pozwolić Lombok wygenerować metodę toString dla Ciebie.

W tym:

  1. Wystarczy dodać Lombok do projektu
  2. Dodaj adnotacji @ToString definicji klasy
  3. Kompilujemy klasa/projekt, a to jest zrobione

Na przykład w twoim przypadku Twoja klasa będzie wyglądać tak:

@ToString 
public class Contact { 
    private String name; 
    private String location; 
    private String address; 
    private String email; 
    private String phone; 
    private String fax; 

    // Getters and setters. 
} 

Przykład wyjścia jest w tym przypadku:

Contact(name=John, location=USA, address=SF, [email protected], phone=99999, fax=88888) 

Więcej szczegółów na temat how to use the annotation @ToString.

UWAGA: Można również pozwolić Lombok wygenerowania getters and setters dla ciebie here to pełna lista funkcji.

0

Jeśli wyjście z ReflectionToStringBuilder.toString() nie jest wystarczająco czytelny dla ciebie, tutaj jest kod, który:
1) sortuje nazwy pól alfabetycznie
2) flagi non-zerowe Pola oznaczone gwiazdkami na początku wiersza

public static Collection<Field> getAllFields(Class<?> type) { 
    TreeSet<Field> fields = new TreeSet<Field>(
      new Comparator<Field>() { 
     @Override 
     public int compare(Field o1, Field o2) { 
      int res = o1.getName().compareTo(o2.getName()); 
      if (0 != res) { 
       return res; 
      } 
      res = o1.getDeclaringClass().getSimpleName().compareTo(o2.getDeclaringClass().getSimpleName()); 
      if (0 != res) { 
       return res; 
      } 
      res = o1.getDeclaringClass().getName().compareTo(o2.getDeclaringClass().getName()); 
      return res; 
     } 
    }); 
    for (Class<?> c = type; c != null; c = c.getSuperclass()) { 
     fields.addAll(Arrays.asList(c.getDeclaredFields())); 
    } 
    return fields; 
} 
public static void printAllFields(Object obj) { 
    for (Field field : getAllFields(obj.getClass())) { 
     field.setAccessible(true); 
     String name = field.getName(); 
     Object value = null; 
     try { 
      value = field.get(obj); 
     } catch (IllegalArgumentException | IllegalAccessException e) { 
      e.printStackTrace(); 
     } 
     System.out.printf("%s %s.%s = %s;\n", value==null?" ":"*", field.getDeclaringClass().getSimpleName(), name, value); 
    } 
} 
uprząż

Test:

public static void main(String[] args) { 
    A a = new A(); 
    a.x = 1; 
    B b = new B(); 
    b.x=10; 
    b.y=20; 
    System.out.println("======="); 
    printAllFields(a); 
    System.out.println("======="); 
    printAllFields(b); 
    System.out.println("======="); 
} 

class A { 
    int x; 
    String z = "z"; 
    Integer b; 
} 
class B extends A { 
    int y; 
    private double z = 12345.6; 
    public int a = 55; 
} 
0

i dostanie moją odpowiedź następująco:

import java.io.IOException; 
import java.io.Writer; 
import java.lang.reflect.Array; 
import java.lang.reflect.Field; 
import java.util.HashMap; 
import java.util.Map; 

public class findclass { 
    public static void main(String[] args) throws Exception, IllegalAccessException { 
     new findclass().findclass(new Object(), "objectName"); 
     new findclass().findclass(1213, "int"); 
     new findclass().findclass("ssdfs", "String"); 
    } 


    public Map<String, String>map=new HashMap<String, String>(); 

    public void findclass(Object c,String name) throws IllegalArgumentException, IllegalAccessException { 
     if(map.containsKey(c.getClass().getName() + "@" + Integer.toHexString(c.hashCode()))){ 
      System.out.println(c.getClass().getSimpleName()+" "+name+" = "+map.get(c.getClass().getName() + "@" + Integer.toHexString(c.hashCode()))+" = "+c);   
      return;} 
     map.put(c.getClass().getName() + "@" + Integer.toHexString(c.hashCode()), name); 
     Class te=c.getClass(); 
     if(te.equals(Integer.class)||te.equals(Double.class)||te.equals(Float.class)||te.equals(Boolean.class)||te.equals(Byte.class)||te.equals(Long.class)||te.equals(String.class)||te.equals(Character.class)){ 
      System.out.println(c.getClass().getSimpleName()+" "+name+" = "+c); 
      return; 
     } 


     if(te.isArray()){ 
      if(te==int[].class||te==char[].class||te==double[].class||te==float[].class||te==byte[].class||te==long[].class||te==boolean[].class){ 
       boolean dotflag=true; 
       for (int i = 0; i < Array.getLength(c); i++) { 
        System.out.println(Array.get(c, i).getClass().getSimpleName()+" "+name+"["+i+"] = "+Array.get(c, i)); 
       } 
       return; 
      } 
      Object[]arr=(Object[])c; 
      for (Object object : arr) { 
       if(object==null)  
        System.out.println(c.getClass().getSimpleName()+" "+name+" = null"); 
       else { 
        findclass(object, name+"."+object.getClass().getSimpleName()); 
       } 
      } 


     } 

     Field[] fields=c.getClass().getDeclaredFields(); 
     for (Field field : fields) { 
      field.setAccessible(true); 

      if(field.get(c)==null){ 
       System.out.println(field.getType().getSimpleName()+" "+name+"."+field.getName()+" = null"); 
       continue; 
      } 

      findclass(field.get(c),name+"."+field.getName()); 
     } 
     if(te.getSuperclass()==Number.class||te.getSuperclass()==Object.class||te.getSuperclass()==null) 
      return; 
     Field[]faFields=c.getClass().getSuperclass().getDeclaredFields(); 

     for (Field field : faFields) { 
      field.setAccessible(true); 
       if(field.get(c)==null){ 
        System.out.println(field.getType().getSimpleName()+" "+name+"<"+c.getClass().getSuperclass().getSimpleName()+"."+field.getName()+" = null"); 
        continue; 
       } 
       Object check=field.get(c); 
       findclass(field.get(c),name+"<"+c.getClass().getSuperclass().getSimpleName()+"."+field.getName()); 

     } 

    } 

    public void findclass(Object c,String name,Writer writer) throws IllegalArgumentException, IllegalAccessException, IOException { 
     if(map.containsKey(c.getClass().getName() + "@" + Integer.toHexString(c.hashCode()))){ 
      writer.append(c.getClass().getSimpleName()+" "+name+" = "+map.get(c.getClass().getName() + "@" + Integer.toHexString(c.hashCode()))+" = "+c+"\n");   
      return;} 
     map.put(c.getClass().getName() + "@" + Integer.toHexString(c.hashCode()), name); 
     Class te=c.getClass(); 
     if(te.equals(Integer.class)||te.equals(Double.class)||te.equals(Float.class)||te.equals(Boolean.class)||te.equals(Byte.class)||te.equals(Long.class)||te.equals(String.class)||te.equals(Character.class)){ 
      writer.append(c.getClass().getSimpleName()+" "+name+" = "+c+"\n"); 
      return; 
     } 


     if(te.isArray()){ 
      if(te==int[].class||te==char[].class||te==double[].class||te==float[].class||te==byte[].class||te==long[].class||te==boolean[].class){ 
       boolean dotflag=true; 
       for (int i = 0; i < Array.getLength(c); i++) { 
        writer.append(Array.get(c, i).getClass().getSimpleName()+" "+name+"["+i+"] = "+Array.get(c, i)+"\n"); 
       } 
       return; 
      } 
      Object[]arr=(Object[])c; 
      for (Object object : arr) { 
       if(object==null){ 
        writer.append(c.getClass().getSimpleName()+" "+name+" = null"+"\n"); 
       }else { 
        findclass(object, name+"."+object.getClass().getSimpleName(),writer); 
       } 
      } 


     } 

     Field[] fields=c.getClass().getDeclaredFields(); 
     for (Field field : fields) { 
      field.setAccessible(true); 

      if(field.get(c)==null){ 
       writer.append(field.getType().getSimpleName()+" "+name+"."+field.getName()+" = null"+"\n"); 
       continue; 
      } 

      findclass(field.get(c),name+"."+field.getName(),writer); 
     } 
     if(te.getSuperclass()==Number.class||te.getSuperclass()==Object.class||te.getSuperclass()==null) 
      return; 
     Field[]faFields=c.getClass().getSuperclass().getDeclaredFields(); 

     for (Field field : faFields) { 
      field.setAccessible(true); 
       if(field.get(c)==null){ 
        writer.append(field.getType().getSimpleName()+" "+name+"<"+c.getClass().getSuperclass().getSimpleName()+"."+field.getName()+" = null"+"\n"); 
        continue; 
       } 
       Object check=field.get(c); 
       findclass(field.get(c),name+"<"+c.getClass().getSuperclass().getSimpleName()+"."+field.getName(),writer); 

     } 
    } 

}