Dart 是否重用 DateTime 实例?

Does Dart reuse DateTime instances?

我正在摆弄 GlobalObjectKey,我的对象是 DateTime 个实例。我注意到如果我创建相同日期和时间的新实例,我会得到相同的实例 "ID":

DateTime newInstance = new DateTime.fromMicrosecondsSinceEpoch(datetime.microsecondsSinceEpoch);

我的调试打印显示有两个具有相同 ID 的独立密钥:

[GlobalObjectKey DateTime#f056e] // Key assigned to Widget1
[GlobalObjectKey DateTime#f056e] // Key assigned to Widget2

然而,尽管密钥似乎是重复的,但我似乎没有收到任何 widget/build 错误。

这是我正在做的一个更完整的例子:

class DateTimeKey{
  GlobalObjectKey key;
  DateTimeKey(DateTime datetime){
    DateTime newInstance = new DateTime.fromMicrosecondsSinceEpoch(datetime.microsecondsSinceEpoch);
    key = new GlobalObjectKey(newInstance);
  }
}

...

List<DateTimeKey> _bookingListMonthKeys = [];
List<DateTimeKey> _bookingListDayKeys = [];

DateTimeKey _monthKey = new DateTimeKey(theDate);
_bookingListMonthKeys.add(_monthKey);

DateTimeKey _dayKey = new DateTimeKey(theDate); // theDate here refers to the same DateTime instance as above
_bookingListDayKeys.add(_dayKey);

即使我循环遍历两个列表并像这样交叉引用它们

  _bookingListDayKeys.forEach((dayKey){
    _bookingListMonthKeys.forEach((monthKey){
      if( identical(dayKey, monthKey) )
        print('Identical DateTimeKeys found: $dayKey, $monthKey');

      if( identical(dayKey.key, monthKey.key) )
        print('Identical GlobalObjectKeys found: ${dayKey.key}, ${monthKey.key}');
    });
  });

它没有显示任何重复项,但上面的打印输出显然具有相同的 "id" (#f056e)。谁能解释一下这是怎么回事?

所以我想我明白这是怎么回事了。

首先,问题中的散列数来自 hashCode property of the DateTime instance. This is used for comparisons by the == operator,因此对于代表同一时刻的两个 DateTime 实例来说,散列数是相同的。

旁注:实际打印的字符串 (#f056e) 似乎是 hashCode 的十六进制表示的最后 5 个字符,这是一个 int.

但是,hashCode 没有被 GlobalObjectKey 使用。相反,它使用 dart:core 中的 identityhashCode() 方法:

Returns the identity hash code of object.

Returns the same value as object.hashCode if object has not overridden Object.hashCode. > Returns the value that Object.hashCode would return on this object, even if hashCode has > been overridden.

This hash code is compatible with identical.

当从同一时刻创建两个不同的 DateTime 实例时,它们的 hashCode 属性将相等,但 identityHashCode() 的结果将不同。所以基本上看起来 identityHashCode() 是我们将得到的对象的实际 "memory address" 最接近的替代品。

DateTime instance1 = DateTime.now();
DateTime instance2 = DateTime.fromMicrosecondsSinceEpoch(instance1.microsecondsSinceEpoch);
print('hashCode: ${instance1.hashCode}, ${instance2.hashCode}   identityHashCode: ${identityHashCode(instance1)}, ${identityHashCode(instance2)}');

将导致:

I/flutter (23321): hashCode: 89064814, 89064814   identityHashCode: 383428552, 594747591

现在可以清楚地看到两个实例的 hashCode 相等,但 identityHashCode(DateTime) 不同,这意味着它们实际上是不同的实例,但在比较它们的 hashCode 时相等属性 或进行 == 操作。

为什么打印 GlobalObjectKey 会打印其值的 hashCode 虽然我仍然无法理解,这就是让我从一开始就放弃的原因。