1:只要提到增强,我的第一思路就是代理,动态代理。但是仅仅是一个toString其实没必要使用代理模式了,有点大材小用了(动态代理其实也是最后通过反射生成toString的方法)。
2:简单粗暴,可以自己写一个ToStringUtils工具类,使用反射获取所有字段然后拼接生成toString,有了这个思路其实实现很容易了。但是每次新项目频繁导入自己的工具类对项目而言还是相对不便利,最好还是利用现有的轮子,那就是apache commons lang3 工具包了,方法为:org.apache.commons.lang3.builder.ReflectionToStringBuilder#toString(java.lang.Object), 翻阅源码就可以知道底层就是使用的反射实现,部分源码:
org.apache.commons.lang3.builder.ReflectionToStringBuilder#toString()
public String toString() { if (this.getObject() == null) { return this.getStyle().getNullText(); } Class<?> clazz = this.getObject().getClass(); this.appendFieldsIn(clazz); // 重点关注 while (clazz.getSuperclass() != null && clazz != this.getUpToClass()) { clazz = clazz.getSuperclass(); this.appendFieldsIn(clazz); } return super.toString(); }
重点关注方法:
protected void appendFieldsIn(final Class<?> clazz) { if (clazz.isArray()) { this.reflectionAppendArray(this.getObject()); return; } final Field[] fields = clazz.getDeclaredFields(); AccessibleObject.setAccessible(fields, true); for (final Field field : fields) { final String fieldName = field.getName(); if (this.accept(field)) { try { // Warning: Field.get(Object) creates wrappers objects // for primitive types. final Object fieldValue = this.getValue(field); if (!excludeNullValues || fieldValue != null) { this.append(fieldName, fieldValue); } } catch (final IllegalAccessException ex) { //this can't happen. Would get a Security exception // instead //throw a runtime exception in case the impossible // happens. throw new InternalError("Unexpected IllegalAccessException: " + ex.getMessage()); } } } }
该工具还支持生成toString字符串的样式:
String toString = ReflectionToStringBuilder.toString(new User("daxin", 18), ToStringStyle.JSON_STYLE); System.out.println(toString);
输出:
String toString = ReflectionToStringBuilder.toString(new User("daxin", 18), ToStringStyle.NO_CLASS_NAME_STYLE); System.out.println(toString);
翻阅了一下源码,其实没有太多高深的东西,更多东西还是需要自己的探索的。