【问题标题】:Why does the Date class object prints today's date instead of reference of Date class为什么 Date 类对象打印今天的日期而不是 Date 类的引用
【发布时间】:2014-02-06 16:36:34
【问题描述】:

当我们创建一个对象时,该对象会有一个类的数据成员和方法的引用。

 For Eg: TestObject obj = new TestObject();
         System.out.println("Test Object is:"+obj);

据我所知,new 运算符所做的是,它为指定的类(变量和方法)创建/分配内存块,并将该引用分配给左侧变量(obj)。所以,上面的 print 语句打印了 TestObject 类的引用。

但是,我的问题是,当我们为 Date 类创建一个对象并打印该对象时,它会打印今天的日期。

 For eg: Date date = new Date();
         System.out.println("Date Object is:"+date);

上面的代码打印今天的日期。为什么以及如何打印日期而不是日期类参考。请帮帮我。

对不起,如果这是一个愚蠢的问题。即使这很愚蠢,我也没有这个问题的答案。

简要说明将是可观的。

【问题讨论】:

    标签: java date


    【解决方案1】:

    当您使用实例的引用进行打印时,在内部,它被称为类的toString() 方法。在Date 类中,toString() 方法返回它包含的任何日期。

    日期api'stoString()方法说,

    Converts this Date object to a String of the form:
     dow mon dd hh:mm:ss zzz yyyy
    

    如果您有意义地覆盖类中的 toString() 方法,则将打印从该方法返回的任何内容,而不是参考内存值。

    【讨论】:

    • +1 - 对 toString() 的内部调用是打印对象时的默认行为。
    • 是的。知道了。并执行了一个测试程序。谢谢。
    【解决方案2】:

    由于Date中的toString()实现,请查看java.util.Date源代码(链接到openjdk7实现)

    Javadoc 引用:

    将此Date 对象转换为以下形式的String

    dow mon dd hh:mm:ss zzz yyyy

    【讨论】:

      【解决方案3】:

      因为Date() 类的toString()

        public String toString() {
          // "EEE MMM dd HH:mm:ss zzz yyyy";
          BaseCalendar.Date date = normalize();
          StringBuilder sb = new StringBuilder(28);
          int index = date.getDayOfWeek();
          if (index == gcal.SUNDAY) {
              index = 8;
          }
          convertToAbbr(sb, wtb[index]).append(' ');                        // EEE
          convertToAbbr(sb, wtb[date.getMonth() - 1 + 2 + 7]).append(' ');  // MMM
          CalendarUtils.sprintf0d(sb, date.getDayOfMonth(), 2).append(' '); // dd
      
          CalendarUtils.sprintf0d(sb, date.getHours(), 2).append(':');   // HH
          CalendarUtils.sprintf0d(sb, date.getMinutes(), 2).append(':'); // mm
          CalendarUtils.sprintf0d(sb, date.getSeconds(), 2).append(' '); // ss
          TimeZone zi = date.getZone();
          if (zi != null) {
              sb.append(zi.getDisplayName(date.isDaylightTime(), zi.SHORT,Locale.US)); 
             // zzz
          } else {
              sb.append("GMT");
          }
          sb.append(' ').append(date.getYear());  // yyyy
          return sb.toString();
      }
      

      【讨论】:

        【解决方案4】:

        正如其他答案正确指出的那样,Java 中的所有类都有一个从超父类Object 继承的toString 方法。

        每个类都应该覆盖“toString”

        如果特定类的程序员选择不使用自己的实现覆盖toString 方法,则她的类将继承默认实现。该默认实现输出您描述的变量引用信息。正如 Object 类文档所述,您可以有效地得到这个……

        getClass().getName() + '@' + Integer.toHexString(hashCode())
        

        toString 的覆盖实现究竟应该包含哪些内容? Sun/Oracle 文档说……

        一般来说,toString 方法返回一个“以文字形式表示”该对象的字符串。结果应该是一个简洁但信息丰富的表示,易于人们阅读。建议所有子类重写此方法。

        辩论

        许多程序员都在争论toString 中究竟应该实现什么。问题是toString 在各种情况下使用。编程时,我们使用System.out.println 调用该方法,将值转储到控制台进行调试。另一个上下文是日志记录,在扩展测试期间记录值。或者我们可能会在生产过程中进行此类日志记录。另一个上下文是生成一个字符串,用于在用户界面中显示消息或错误报告。

        一些程序员认为对象应该有多个这样的方法,以适应这些不同的目的。但是在 Java 中,我们为每个对象内置的只是一个这样的方法,toString。随心所欲。

        java.util.Date — 实现“toString”的错误方式

        java.util.Date 类的设计者决定他们的toString 实现将采用实际上没有时区信息的日期的值,然后应用JVM 的默认时区来输出日期时间以一种古怪尴尬的格式。

        这种格式的一个坏处是使用了三个字母的时区代码。不幸的是,这些代码既不是标准化的也不是唯一的,存在常见的重复代码,例如爱尔兰标准时间和印度标准时间的 IST。避免使用这些 3 字母代码,而是使用 proper time zone names

        关于 java.util.Date 的 toString 最糟糕的事情是它给人一种非常混乱的印象,即 Date 有一个时区,而实际上它没有。这种混乱在 StackOverflow 和其他地方造成了无穷无尽的重复问题。所以 java.util.Date 是一个伟大的案例研究如何编写toString实现。

        幸运的是,经过很长时间的等待,旧的 java.util.Date 和 java.util.Calendar 类将被 Java 8 中的新 java.time.* package 取代。这个包由JSR 310 定义,灵感来自Joda-Time

        Joda-Time – 实现“toString”的正确方法

        Joda-Time 是捆绑的 java.util.Date/Calendar 类的流行替代品。 Joda-Time 作为一个开源的免费库。

        Joda-Time 中DateTime 对象的实现使用基于ISO 8601 格式的内置格式化程序。出于多种原因,该 ISO 格式是一种很好的格式。原因之一是该标准清晰而准确。另一个是格式是直观的,无论文化规范如何,全球任何人都可以确定其含义。另一个好处是,作为没有空格的单个连续字符串,可以更轻松地在编程中处理和解析它,尽管从技术上讲,中间的“T”是可选的(但强烈建议使用)。包含时区信息,但使用明确的小时和分钟偏移量,而不是 3 个字母的代码。

        总而言之,这是一个很好的例子来说明如何实现toString

        Joda-Time 2.3 中的示例代码

        java.util.Date date = new java.util.Date();
        

        通常指定时区比依赖默认时区更好。

        DateTimeZone timeZone = DateTimeZone.forID( "Asia/Kolkata" ); // Formerly known as Calcutta, India. 
        

        将该 Date 对象转换为 Joda-Time DateTime 对象。或者您可以从头开始创建一个新的 DateTim。

        DateTime dateTime_India = new DateTime( date, timeZone ); // Or… new DateTime( timeZone );
        

        如果需要,您可以通过在第一个实例的基础上创建另一个实例来转换为UTC/GMT(无时区偏移)。 Joda-Time 一般遵循immutable object 设计。生成一个新对象,与原始对象类似,但调整了某些方面,例如时区偏移。

        DateTime dateTime_UtcGmt = dateTime_India.toDateTime( DateTimeZone.UTC ); 
        

        转储到控制台,使用“toString”的默认实现,该实现使用 ISO 8601 格式的内置 formatter。知道 Joda-Time 提供了丰富的工具来输出许多不同格式的日期时间字符串表示,但这里的重点是 default,即“toString”的实现。这些println 行中的每一行都隐式调用对象的toString 方法。

        System.out.println( "date: " + date );
        System.out.println( "timeZone: " + timeZone );
        System.out.println( "dateTime_India: " + dateTime_India );
        System.out.println( "dateTime_UtcGmt: " + dateTime_UtcGmt );
        

        运行时……

        date: Thu Feb 06 00:17:19 PST 2014
        timeZone: Asia/Kolkata
        dateTime_India: 2014-02-06T13:47:19.796+05:30
        dateTime_UtcGmt: 2014-02-06T08:17:19.796Z
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-08-03
          • 2015-01-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多