Java:设置对象创建的时间

时间:2014-09-15 15:43:24

标签: java

Java新手问题。 我想低估如何设置和存储对象被装箱的时间的原则。

代码:

封装

package com.Test;

public class Test_package {

    private static int hour;
    private static int minute;
    private static int second;


    public Test_package(){
        this.hour = (int)(((System.currentTimeMillis()/1000) /60) / 60) % 24 + 3;
        this.minute = (int)((System.currentTimeMillis() / 1000) /60 ) % 60;
        this.second =(int)(System.currentTimeMillis() /1000) % 60;      
    }

    public void getTime(){
        System.out.println("Stundas:" + this.hour +" minute: " +this.minute + " sekunde:"+ this.second);
    }
}

主要类别:

import com.Test.*;
public class Test {

    public static void main(String[] args) {

        Test_package objectTime = new Test_package();

        objectTime.getTime();
    }
}

我得到的是当前时间,这很好,但我想了解创建对象时创建对象时的原理,所以当我调用方法时.getTime()我得到时间创建对象时不是当前时间。

换句话说,我该如何存储时间。 或者我的代码是好的,但我不会看到我想要的结果,因为主要类重复执行它重新创建对象,因此我得到当前时间。

5 个答案:

答案 0 :(得分:3)

你的代码是99%的代码。但是有一些问题。

1)说服自己显示创建时间,而不是现在在调用getTime()之前进行睡眠

Test_package objectTime = new Test_package();
Thread.sleep(300000); // sleep 5 mins
objectTime.getTime();

2)构造函数对getCurrentTime进行多次调用;大多数情况下,如果系统在错误的时刻拨打电话,这将是好的,那么你冒险剪切时间戳。鉴于呼叫的粒度,这只会在每分钟结束时出现问题,就像时钟即将翻身一样。要解决此问题,请调用System.currentTimeMillis一次并重用该值。

public Test_package(){
    long nowMillis = System.currentTimeMillis();

    this.hour = (int)(((nowMillis/1000) /60) / 60) % 24 + 3;
    this.minute = (int)((nowMillis / 1000) /60 ) % 60;
    this.second =(int)(nowMillis /1000) % 60;      
}

3)您正在重复使用相同的变量,因此如果您创建了多个对象,则只会存储最后一个对象的时间戳。要修复此问题,请从小时,分钟和秒中删除每个字段中的关键字static。

4)你已经将时区硬编码为UTC的+3,可能不是你的问题,但值得引起人们的注意。执行此操作的常规方法是仅将millis存储为字段,然后使用time formater进行打印,可能是新的Date(millis).toString()就足够了,它将使用平台的默认时区。

5)你还应该知道currentTimeMillis可以以大于1的增量递增,从而报告在相同的时间戳创建了更多的对象。这取决于您运行的操作系统,而您几乎无法控制。在System上有一个单独的调用,它返回一个纳秒的相对计数并且具有更精细的粒度,但是该调用不会给出绝对时间,因此不适合你。我纯粹将其称为fyi。

答案 1 :(得分:1)

您的代码基本上没问题。

public class Test {

    public static void main(String[] args) throws Exception {

        Test_package objectTime = new Test_package();
        Thread.sleep(300000); // sleep 5 mins
        objectTime.getTime();
    }

}

尝试以上操作。

您的主要“问题”仅在于您致电getTime()
在创建对象后立即创建。试着睡在两者之间 然后getTime将打印5分钟前的时间,而不是
当前时间。

答案 2 :(得分:1)

由于您的时间变量为static,因此每个变量只有一个实例,因此如果您创建了多个对象并从其中任何一个(或从类中)获取时间,那么您就可以了得到最后一个对象的创建时间。

也许这就是您的意图,但除此之外,只需从这些变量中删除static关键字。

答案 3 :(得分:1)

您不想使用静态字段,或者最终会保存创建的 last 对象,而不是每个对象的创建时间。您还需要以毫秒为单位存储时间。

package com.Test;
public class Test_package {

    private final Date created = new Date();

    public void getTime() {
        SimpleDateFormat sdf = new SimpleDateFormat(
                                   "'Stundas:'HH' minute: 'mm' sekunde:'ss");
        System.out.println(sdf.format(created));
    }
}

答案 4 :(得分:0)

static

正如其他正确答案所述,您不应该将static用于单个对象(实例)。

“静态”这个词有很长的扭曲历史,有C和Java,我们可以忽略它。结果是,在Java中,“静态”一词意味着“不是面向对象的”。 “静态”一词意味着我们希望在整个工作会话的内存中只保留一些数据(“状态”)。没有更好的地方可以保留它,我们将这些数据粘贴到内存中类的自己的表示上。使用普通的面向对象的非静态成员变量,每个对象(实例)都有自己的数据。对于Person个对象,每个Person对象都有自己的firstNamephoneNumber值,而Person类上的静态变量在内存周期中只有一个值。

具有非OOP语言背景的程序员可能会被static个变量所吸引,因为它们看起来像全局变量。实际上,您可以使用静态变量和静态方法成功地创建Java程序,代码类似于非OOP语言。但是你会错过OOP带来的力量和简洁性。

请参阅问题What does the 'static' keyword do in a class?

日期时间类型

在处理日期时间数据时,通常最好使用日期时间数据类型。跟踪时间以毫秒为单位(自epoch以来的计数)很快变得笨拙,令人困惑,并且难以调试。此外,日期工作令人惊讶地复杂和棘手。只需在StackOverflow.com上搜索java date即可查看日期时间工作的复杂程度。

例如,您的问题代码错误地将System.currentTimeMillis视为时间,实际上它是日期时间,从1970年的第一个时刻算起UTC时区。

您不会将数字作为位或文本处理为八位字节;我们已经将类定义为数据类型来处理和隐藏细节。所以你应该是日期时间课程,而不是自上帝以来的计数。

日期时间库

对于Java,我们有两个很好的日期时间库:

两者都有优势。幸运的是,你可以使用哪种更适合特定情况来混合和匹配两者。

Java还有一些用于日期工作的旧类,java.util.Date,java.util.Calendar,java.text.SimpleDateFormat和其他(都在java.time包之外)。不幸的是,这些类是众所周知的麻烦,历史和演变令人困惑,设计和实现都存在问题。避免他们。他们已被java.time取代。如果需要,您可以转换为Joda-Time以及java.time。

物件死亡

在Java程序结束的main方法结束时。内存中的所有数据都被清除,消失了。因此,如果您想要更长时间地存储数据,则必须保留它。也许写一个文件,或者把它放到数据库中。

在你的问题代码和下面的例子中,每次执行/运行程序时都会从头开始重新创建对象。因此,每个对象都会获得一个新的日期时间。

示例代码

以下是Joda-Time 2.4中的一些示例代码。

我们有一个“Animal”类,可以跟踪它的对象何时被实例化(在运行时分配一块内存来存储其数据)。该时刻记录在Joda-Time库中定义的DateTime类型的成员变量“objectCreation”中。

不是隐式依赖JVM的当前默认时区,而是分配时区。在这种情况下,我从proper time zone names列表中任意选择内罗毕。

作为使用static的一个例子,我创建了三个常量,定义了预期的物种。这是一个实际的例子,我们避免和检测诸如“狗”的“dg”之类的拼写错误。

此示例捕获执行的开始和结束时间以显示一段时间。

package com.example.yourpackage;

import java.util.concurrent.TimeUnit;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Interval;
import org.joda.time.Period;

public class Animal
{
    // Static vars exist once in memory, and can be accessed by *any* Animal object (or other objects).
    static final String SPECIES_DOG = "dog";
    static final String SPECIES_CAT = "cat";
    static final String SPECIES_BIRD = "bird";

    // Each instance (each Animal object) has its own value for each of these member variables.
    DateTime objectCreation = null;
    String species = null;
    String name = null;

    // Constructor method.
    public Animal( String speciesArg , String nameArg )
    {
        if ( ( speciesArg.equals( Animal.SPECIES_DOG ) ) || ( speciesArg.equals( Animal.SPECIES_CAT ) ) || ( speciesArg.equals( Animal.SPECIES_BIRD ) ) ) {
            // If we were passed an expected species, proceed.
            this.objectCreation = DateTime.now( DateTimeZone.forID( "Africa/Nairobi" ) ); // Or DateTimeZone.UTC
            this.species = speciesArg;
            this.name = nameArg;
        } else {
            // Else we were passed an unexpected species.
            // FIXME: Handle this error condition…
        }
    }

    @Override
    public String toString()
    {
        return "Animal{" + "objectCreation=" + objectCreation + ", species=" + species + ", name=" + name + '}';
    }

    public static void main( String[] args )
    {
        DateTime start = DateTime.now( DateTimeZone.forID( "Africa/Nairobi" ) );

        Animal x = new Animal( "dog" , "Buddy" );
        try {
            TimeUnit.SECONDS.sleep( 3 );
        } catch ( InterruptedException ex ) {
            System.out.println( "Exception: " + ex );  // FIXME: Handle this error condition…
        }

        Animal y = new Animal( "dog" , "Rover" );
        try {
            TimeUnit.SECONDS.sleep( 5 );
        } catch ( InterruptedException ex ) {
            System.out.println( "Exception: " + ex );  // FIXME: Handle this error condition…
        }

        Animal z = new Animal( "bird" , "Polly" );

        DateTime stop = DateTime.now( DateTimeZone.forID( "Africa/Nairobi" ) );
        Interval interval = new Interval( start , stop );
        Period period = interval.toPeriod();

        System.out.println( "x: " + x );
        System.out.println( "y: " + y );
        System.out.println( "z: " + z );
        System.out.println( "Interval: " + interval + "  Period: " + period );
    }

}

跑步时。

x: Animal{objectCreation=2014-09-16T10:17:00.636+03:00, species=dog, name=Buddy}
y: Animal{objectCreation=2014-09-16T10:17:03.635+03:00, species=dog, name=Rover}
z: Animal{objectCreation=2014-09-16T10:17:08.634+03:00, species=bird, name=Polly}
Interval: 2014-09-16T10:17:00.575+03:00/2014-09-16T10:17:08.634+03:00  Period: PT8.059S

命名

提示:我建议避免使用“包”这个词作为命名类的一部分。单词package是用于定义类的关键字,如问题代码的第一行所示。因此,将“包”混合到您的班级名称会令人困惑。