Печать всех значений переменных из класса
у меня есть класс с информацией о человеке, который выглядит примерно так:
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.
}
Я хочу toString()
вернуться this.name +" - "+ this.locations + ...
для всех переменных. Я пытался реализовать его с помощью отражения, как показано на этом вопросе, но я не могу печатать переменные экземпляра.
что такое правильный способ решить эту проблему?
9 ответов:
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(); }
почему вы хотите изобретать колесо, когда есть opensource, которые уже делают эту работу довольно хорошо.
в Apache common-langs и весна поддержка очень гибкий шаблон строителя
для apache, вот как вы делаете это рефлексивно
@Override public String toString() { return ToStringBuilder.reflectionToString(this); }
вот как вы это делаете, если вы хотите печатать только те поля, которые вас волнуют.
@Override public String toString() { return new ToStringBuilder(this) .append("name", name) .append("location", location) .append("address", address) .toString(); }
Вы можете пойти так далеко, как "стиль" вашего вывода на печать с помощью не по умолчанию ToStringStyle или даже настроить его с вашим собственным стилем.
Я лично не пробовал весну ToStringCreator API, но это выглядит очень похоже.
Если вы используете Eclipse, это должно быть легко:
1.Нажмите Alt+Shift+S
2.Выбрать "Создать метод toString()..."
наслаждайтесь! Вы можете иметь любой шаблон toString () s.
Это также работает с геттер/сеттеры.
Generic toString () one-liner, используя отражение и настройку стиля:
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); }
при доступе к значению поля, передайте экземпляр, а не null.
Почему бы не использовать генерацию кода здесь? Затмение, к примеру, будет генерировать reasoble реализации toString для вас.
еще один простой подход, чтобы позволить
Lombok
создатьtoString
способ для вас.для этого:
- просто добавить
Lombok
в проекте- добавить аннотации
@ToString
к определению вашего класса- скомпилируйте свой класс / проект, и это будет сделано
так, например, в вашем случае, ваш класс будет выглядеть так:
@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. }
пример вывода в этом дело:
Contact(name=John, location=USA, address=SF, email=foo@bar.com, phone=99999, fax=88888)
подробнее о как использовать аннотации
@ToString
.Примечание: вы можете
Lombok
создать геттеры и сеттеры для вас здесь полный список возможностей.
добавление с ответом @cletus, вы должны извлечь все поля модели( верхняя иерархия) и установить
field.setAccessible(true)
для доступа к закрытым членам. Вот полный фрагмент:@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; }
Если выход из
ReflectionToStringBuilder.toString()
недостаточно читаемым для вас, вот код:
1) сортирует имена полей в алфавитном порядке
2) флаги ненулевых полей со звездочками в начале строки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); } }
теста:
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; }
Я вам отвечу следующим образом:
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); } } }