Java 为什么ToString Builder的工作不一致?

Java 为什么ToString Builder的工作不一致?,java,tostring,apache-commons,apache-commons-lang,apache-commons-lang3,Java,Tostring,Apache Commons,Apache Commons Lang,Apache Commons Lang3,在下面的代码中,为什么这两行包含System.out.println(person)产生不同的输出?第二行间接调用方法Job.toString生成字符串“Manager”,但第一行神秘地没有生成Job@28f67ac7。介于person.put(“a”、“b”)之间的一行对我来说似乎没有什么区别 代码: 有两件事导致输出发生变化: toString Builder避免在相等实例上调用toString(),以避免无限递归 Person和Job类继承HashMap的equals()方法,导致new

在下面的代码中,为什么这两行包含
System.out.println(person)产生不同的输出?第二行间接调用方法
Job.toString
生成字符串
“Manager”
,但第一行神秘地没有生成
Job@28f67ac7
。介于
person.put(“a”、“b”)之间的一行对我来说似乎没有什么区别

代码:


有两件事导致输出发生变化:

  • toString Builder避免在相等实例上调用toString(),以避免无限递归
  • Person和Job类继承HashMap的equals()方法,导致
    newPerson().equals(newjob())==true

这意味着,当示例中的person和person.job保持相等时,toString Builder将不会调用person.job.toString(),但当映射内容更改时,将调用person.job.toString()。

我是否可以建议像这样扩展
HashMap
几乎肯定没有您想象的那么有用。
Person
不是
HashMap
;不过,它们可能有一个属性的
HashMap
,因此组合在这里是更合适的关系。@Andy Turner我同意,扩展HashMap在本例中没有用处。但是考虑到这个例子是人为的,你会期望得到不一致的结果吗?@BrianSchack不,我不会。除了
ToStringBuilder
类的实现不佳之外,我看不到对这种行为的任何逻辑解释。@cricket\u 007覆盖注释是可选的。我添加了它,但它并没有改变输出。@AndyTurner是的,我担心我可能在Apache Commons中偶然发现了一个bug。我一直在阅读源代码,但我似乎找不到它在哪里。谢谢你的解释!
import java.util.*;
import org.apache.commons.lang3.builder.*;

class Job extends HashMap<String, String> {
    @Override public String toString() {
        return "Manager";
    }
}

class Person extends HashMap<String, String> {
    Job job;

    Person() {
        this.job = new Job();
    }

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

class Test {
    public static void main(String[] args) {
        Person person = new Person();
        System.out.println(person);
        person.put("a", "b");
        System.out.println(person);
    }
}
Person@2b80d80f[job=Job@28f67ac7,threshold=0,loadFactor=0.75]
Person@2b80d80f[job=Manager,threshold=12,loadFactor=0.75]