8


我试图通过在多个线程中使用相同的 SimpleDateFormat 实例来复制错误。但是,我遇到了另一个问题,没有找到任何答案。

这个简单的代码块复制了我看到的问题。

DateFormat d1 = new SimpleDateFormat("ddMMyyyy");
DateFormat d2 = new SimpleDateFormat("ddMMyyyy");
DateFormat d3 = new SimpleDateFormat("ddMMyy");
System.out.println("d1 = " + d1);
System.out.println("d2 = " + d2);
System.out.println("d3 = " + d3);

java 7(1.7_0_21)下这个操作的结果如下

d1 = java.text.SimpleDateFormat@c5bfbc60
d2 = java.text.SimpleDateFormat@c5bfbc60
d3 = java.text.SimpleDateFormat@b049fd40

如您所见,尽管我为 d1 和 d2 创建了新对象,但它们最终成为相同的引用。d3 最终成为一个新实例,因为模式不同。

java 编译/运行时是否进行此优化?任何指示都会有所帮助

4

3 回答 3

14

SimpleDateFormatnor DateFormat( SimpleDateFormatsuperclass) nor Format( DateFormatsuperclass) 有一个toString()实现,所以toString()Object类实际执行,其代码是:

public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

现在,SimpleDateFormat生成了 hashCode:

public int hashCode()
{
    return pattern.hashCode();
    // just enough fields for a reasonable distribution
}

这意味着如果您创建多个SimpleDateFormat具有相同的实例pattern,就像您的情况一样,它们将具有相同的hashCode,因此toString()将为这些实例返回相同的值。

此外,正如 rixmath 发现的那样,SimpleDateFormat具有相同的实例pattern也将是相等的。

于 2013-05-24T09:53:43.637 回答
6

SimpleDateFormat实际上是hashCode通过返回模式的哈希码来实现的。

您可以使用以下方法验证是否存在实际不同的对象System.identityHashCode()

System.out.println("d1 = " + d1 + " / " + System.identityHashCode(d1));
System.out.println("d2 = " + d2 + " / " + System.identityHashCode(d2));
System.out.println("d3 = " + d3 + " / " + System.identityHashCode(d3));

这将打印 3 个不同的值。

于 2013-05-24T10:01:18.867 回答
5

它们是不同的实例,试试这个

    DateFormat d1 = new SimpleDateFormat("ddMMyyyy");
    DateFormat d2 = new SimpleDateFormat("ddMMyyyy");
    System.out.println(d1 == d2);

它打印

false

同样java.text.SimpleDateFormat@c5bfbc60,它们基于类名和hashCode。根据 Object.hashCode API,它不一定为不同的对象返回不同的值

于 2013-05-24T10:01:07.380 回答