【问题标题】:Issue with Calendar within a while loop在 while 循环中出现日历问题
【发布时间】:2012-05-08 12:58:07
【问题描述】:

我正在开发这个时间容器,它基本上包含一个名为 week 的类的实例,它由 2 个日历实例(开始和结束)和许多其他管理信息(目前不相关)组成

问题是我在 while 循环中创建了这些 Week 实例,并且我看到在创建 week 实例期间(在 while 循环中打印日历毫秒),millis 很好,但是如果我检查内容在周列表中,他们不是! Calendar 的所有实例(开始和结束)在所有周中都包含相同的值。

我写了一些代码让你们清楚地理解问题,有类(Container和BiggerContainer):

public class Container
{
  private static final long serialVersionUID = 1L;

  private Calendar          start;

  private Calendar          end;

  public Container(Calendar start, Calendar end)
  {

    this.start = start;
    this.end = end;

  }

  public Calendar getStart()
  {
    return start;
  }

  public Calendar getEnd()
  {
    return end;
  }
}

Bigger container:

    public class BiggerContainer
{
  private static final long    serialVersionUID = 1L;

  private ArrayList<Container> containerList    = new ArrayList<Container>();

  public void init()
  {

    int i = 0;

    long max = 604800000;

    long nu = Calendar.getInstance().getTimeInMillis();

    Calendar startC = Calendar.getInstance();

    Calendar endC = Calendar.getInstance();

    while (i <= 5)
    {

      startC.setTimeInMillis(nu);
      endC.setTimeInMillis(nu + max);
      System.out.println("At creation time: " + startC.getTimeInMillis() + " / " + endC.getTimeInMillis());
      containerList.add(new Container(startC, endC));

      nu += max;
      i++;
    }
  }

  public void show()
  {

    for (Container c : containerList)
    {

      System.out.println("Start millis: " + c.getStart().getTimeInMillis() + " end millis "
          + c.getEnd().getTimeInMillis());
    }
  }

  /**
   * TEST
   * 
   * @param args
   */
  public static void main(String[] args)
  {

    BiggerContainer bc = new BiggerContainer();

    bc.init();

    bc.show();
  }

}

输出:

At creation time: 1336480993036 / 1337085793036
At creation time: 1337085793036 / 1337690593036
At creation time: 1337690593036 / 1338295393036
At creation time: 1338295393036 / 1338900193036
At creation time: 1338900193036 / 1339504993036
At creation time: 1339504993036 / 1340109793036


Start millis: 1339504993036 end millis 1340109793036
Start millis: 1339504993036 end millis 1340109793036
Start millis: 1339504993036 end millis 1340109793036
Start millis: 1339504993036 end millis 1340109793036
Start millis: 1339504993036 end millis 1340109793036
Start millis: 1339504993036 end millis 1340109793036

正如您在 init() 方法中创建 Container 实例的过程中看到的,Calendar 实例提供了正确的毫秒数,而在 show 方法中,它们打印的都是相同的毫秒数...

你有什么想法吗? 我的印象是这是一个非常新的错误,但我无法弄清楚我在哪里做错了

【问题讨论】:

    标签: java calendar arraylist while-loop


    【解决方案1】:

    您正在为所有容器重用同一个日历实例(startC 和 endC)。在构造函数中创建日历的“克隆”/“副本”或在循环中创建日历实例。

      public Container(Calendar start, Calendar end)
      {
    
        this.start = (Calendar) start.clone();
        this.end = (Calendar) end.clone();
      }
    

    while (i <= 5)
    {
      Calendar startC = Calendar.getInstance();
      Calendar endC = Calendar.getInstance();
      startC.setTimeInMillis(nu);
      endC.setTimeInMillis(nu + max);
      System.out.println("At creation time: " + startC.getTimeInMillis() 
              + " / " + endC.getTimeInMillis());
      containerList.add(new Container(startC, endC));
    
      nu += max;
      i++;
    }
    

    【讨论】:

    • 谢谢,我知道这是一个“简单”的解决方案,但为什么 Calendar.setTimeInMillis() 不改变日历的 MILLISECOND 字段?
    • @JBoy 确实如此。问题是您为所有容器重复使用相同的日历。因此,当您使用 setTimeInMillis 修改 startC(例如)时,实际上是在所有 Container 中修改它,因为它们都使用相同的 startC
    【解决方案2】:

    您可以将时间戳存储在 Container 对象中,例如

    containerList.add(new Container(startC.getTime(), endC.getTime()));
    

    那么您将不会有重复使用日历实例的问题。而且我认为这样会更有效率。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-22
      • 2013-11-17
      • 1970-01-01
      • 2011-06-19
      • 2016-03-01
      • 1970-01-01
      • 2022-06-12
      • 2016-06-22
      相关资源
      最近更新 更多