任何对象的java toString

我有很多数据对象,我希望能够生成表示每个对象的String ,而不需要为每个对象实现toString方法。

我正在考虑获取字段及其值的reflection。

还有其他想法吗?

谢谢。

欢迎您使用雅加达的ToStringBuilder。 它有2种模式,一种是需要使用API​​添加所需的所有字段,另一种是基于reflection:

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

使用JUtils插件在包级别生成toString方法

或者使用reflection你可以尝试这样的事情:

 public static void toString(Object object) throws InvocationTargetException, IllegalArgumentException, IllegalAccessException{ Class c = object.getClass(); Method[] methods = c.getMethods(); for (Method method : methods) { if(method.getName().startsWith("get")){ System.out.println(method.getName()+" -> " +method.invoke(object, null)); } } } 

JUtil插件是最好的,因为如果您需要提供有关该对象的更多信息,这将允许您稍后更改对象的toString。

如果你有很多对象,那么不是在每个类中添加toString而是使用代码检测(你可以在jar中改变.class或者在加载时使用javaagent更改它们)。 例如, AspectJ会有所帮助,但还有很多其他选择。 例如,你可以做这样的事情(使用来自Apache Commons的 AspectJ和ToStringBuilder ):

 @Aspect public class ToStringAspect { @Around("execution(String *.toString()) && target(t) && within(your.target.package.*)") public String toStringCall(Object t) { return ToStringBuilder.reflectionToString(t); } } 

ToStringBuilder非常灵活。 例如,如果您不需要通过设置StandardToStringStyle#setUseClassName(false)来使用类名称使用样式:

  public String toStringCall(Object t) { StandardToStringStyle style = new StandardToStringStyle(); style.setUseClassName(false); style.setUseIdentityHashCode(false); ToStringBuilder builder = new ReflectionToStringBuilder(t, style); return builder.toString(); } 

实现toString方法的方法很少。

  1. 思考(Apache库)

     @Override public String toString(){ return org.apache.commons.lang3.builder.ReflectionToStringBuilder.toString(this); } 
  2. 基于JSON的实现(GSON,Jackson库)

     // GSON library for JSON @Override public String toString(){ return new com.google.gson.Gson().toJson(this); } // Jackson libabry for JSON/YAML @Override public String toString() { try { return new com.fasterxml.jackson.databind.ObjectMapper().writerWithDefaultPrettyPrinter().writeValueAsString(this); } catch (com.fasterxml.jackson.core.JsonProcessingException e) { e.printStackTrace(); } return null; } 
  3. ToStringBuilder(与apache-commons库一起提供)

     @Override public String toString() { return new org.apache.commons.lang3.builder.ToStringBuilder(this). append("field1", field1). append("field2", field2). toString(); } 
  4. 硬核toString()实现

     @Override public String toString() { return new StringBuilder() .append("field1:"+field1) .append("field2:"+field2) .toString(); } 

toString方法由Java中的每个Classinheritance,来自java.lang.Object 。 我看不出你怎么能避免不实现(实际上覆盖) Object.toString 。 此外,为每个类定义方法,而不是为每个对象定义方法。

您可以使用inheritance层次结构来解决此问题,方法是让您的类inheritance自覆盖默认toString实现的公共类。 此实现可以使用reflection来反映类的字段(不是父类,但实际上是当前对象的类),并生成字符串。

如果您根本不想覆盖该方法,也可以调查字节码编织的使用。 就个人而言,我认为投入字节码编织的努力并不值得,特别是当你可以覆盖toString

某种静态String dataToString(Data data)方法可能有效。 我没有任何反思的知识,所以这是我的想法。

方法实现取决于数据对象的设置方式。 inheritance还在继续吗? 如果存在,则可以将超类型对象作为参数传入,并对所有数据全局使用该方法。 您需要在方法中执行一些条件检查或其他forms的逻辑,具体取决于您的程序设置的准确程度,以返回正确的字符串。

有关您的程序的更多信息(如何设置,您想要打印什么,数据对象是什么等)将帮助我更好地回答这个问题:)

如果要为每个对象实现toString(),可以使用AspectJ。 除此之外,你将无法为每个对象实现该方法。

如前所述,您可以使用已经实现的库,如Apache commons-lang的ReflectionToStringBuilder 。 如上所述。

或者用reflectionAPI自己写smt。

这是一些例子

 class ReflectionAnalyzer { private ArrayList visited = new ArrayList(); /** * Converts an object to a string representation that lists all fields. * @param obj an object * @return a string with the object's class name and all field names and * values */ public String toString(Object obj) { if (obj == null) return "null"; if (visited.contains(obj)) return "..."; visited.add(obj); Class cl = obj.getClass(); if (cl == String.class) return (String) obj; if (cl.isArray()) { String r = cl.getComponentType() + "[]{"; for (int i = 0; i < Array.getLength(obj); i++) { if (i > 0) r += ","; Object val = Array.get(obj, i); if (cl.getComponentType().isPrimitive()) r += val; else r += toString(val); } return r + "}"; } String r = cl.getName(); // inspect the fields of this class and all superclasses do { r += "["; Field[] fields = cl.getDeclaredFields(); AccessibleObject.setAccessible(fields, true); // get the names and values of all fields for (Field f : fields) { if (!Modifier.isStatic(f.getModifiers())) { if (!r.endsWith("[")) r += ","; r += f.getName() + "="; try { Class t = f.getType(); Object val = f.get(obj); if (t.isPrimitive()) r += val; else r += toString(val); } catch (Exception e) { e.printStackTrace(); } } } r += "]"; cl = cl.getSuperclass(); } while (cl != null); return r; } }