简体   繁体   English

Java:设置对象创建时间

[英]Java: Setting time of object creation

Java newbie question. Java新手问题。 I want to understated the principle of how it's possible to set and store the time when an object is crated. 我想低估可能设置和存储对象创建时间的原则。

Code: 码:

Package: 包:

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);
    }
}

Main Class: 主类:

import com.Test.*;
public class Test {

    public static void main(String[] args) {

        Test_package objectTime = new Test_package();

        objectTime.getTime();
    }
}

What I get out is the current time, and that's fine, but I want to understand the principle when creating an object the time of the object creation is set, so when I call the method .getTime() I get the time when the object is created not current time. 我得到的是当前时间,这很好,但是我想了解创建对象时的原理,设置了对象创建的时间,所以当我调用方法.getTime()时,我得到了对象的时间不是当前时间创建的。

In other words how can I store the time. 换句话说,我该如何存储时间。 Or is my code OK but I'm not gonna see the result of what I want due to the fact as main class been re-executing over and over it recreates the object thus I get current time. 还是我的代码可以,但是由于主类一遍又一遍地重新执行而无法创建所需的结果,因此我无法看到所需的结果。

You code is 99% of the way there. 您的编码完成了99%。 There are a few issues though. 虽然有一些问题。

1) To convince yourself that you are displaying the creation time, and not just now place a sleep before calling getTime() 1)为了使自己相信自己正在显示创建时间,而不仅仅是在调用getTime()之前先休眠一下

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

2) The constructor makes multiple calls to getCurrentTime; 2)构造函数多次调用getCurrentTime; most of the time this will be fine HOWEVER if the system makes the calls at just the wrong moment, then you risk shearing of the timestamp. 在大多数情况下,这会很好,但是如果系统在错误的时刻进行呼叫,则可能会浪费时间标记。 Given the grain of the calls, this would only be a problem at the end of each minute, just as the clock was about to roll over. 考虑到通话的数量,这只会在每分钟结束时出现问题,就像时钟将要倒计时一样。 To fix this, call System.currentTimeMillis once and reuse the value. 要解决此问题,请一次调用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) You are reusing the same variables, so if you created multiple objects then only the timestamp of the last object would be stored. 3)您正在重用相同的变量,因此,如果创建了多个对象,则仅会存储最后一个对象的时间戳。 To fix, remove the keyword static from each of the fields hour, minute and second. 要解决此问题,请从小时,分钟和秒的每个字段中删除关键字static。

4) You have hard coded the timezone as +3 from UTC, probably not an issue for you but it is worth drawing attention to it. 4)您已将UTC的时区硬编码为+3,这对您来说可能不是问题,但值得引起注意。 The normal way of doing this is to ONLY store the millis as a field, and then print using a time formater, perhaps new Date(millis).toString() would be sufficient and it would use the default timezone of your platform. 这样做的通常方法是只将millis存储为一个字段,然后使用时间格式化程序进行打印,也许新的Date(millis).toString()就足够了,它将使用平台的默认时区。

5) You should also be aware that currentTimeMillis may increment in deltas greater than one, thus reporting that more objects were created at the same timestamp then they really were. 5)您还应该注意,currentTimeMillis的增量可能会大于1,从而报告在同一时间戳创建的对象比实际更多。 This depends on the OS that you are running on, and you have little control over. 这取决于您所运行的操作系统,并且您几乎无法控制。 There is a separate call on System that returns a relative count of nanoseconds and has a finer grain, however that call does not give absolute time and so will not suite you. 在System上有一个单独的调用,该调用返回相对的纳秒计数并具有更精细的粒度,但是该调用不会给出绝对的时间,因此无法满足您的要求。 I mention this purely as an fyi. 我纯粹是出于同情。

Your code is basically OK. 您的代码基本上可以。

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();
    }

}

Try this above. 尝试以上。

Your main "problem" is only that you call getTime() 您的主要“问题”只是调用getTime()
right after creating your object. 在创建对象之后。 Try to sleep in between. 尝试在两者之间睡觉。
Then getTime will print the time from 5 mins ago, not 然后getTime将打印5分钟前的时间,而不是
the current time. 当前时间。

Since your time variables are static , there is only once instance of each of them, so if you create several objects and get the time from any of them (or from the class), you'll get the time when the last object was created. 由于您的时间变量是static ,因此每个变量只有一个实例,因此,如果您创建多个对象并从任何一个(或从类)获取时间,则将获得最后一个对象的创建时间。

Maybe this is what you intended, but otherwise, just remove the static keyword from those variables. 也许这就是您想要的,否则,只需从这些变量中删除static关键字即可。

You don't want to use static fields or you will end up saving the last object created, not the time each object is created. 您不想使用静态字段,否则将最终保存创建的最后一个对象,而不是保存每个对象的创建时间。 Also you just need to store the time in millis. 另外,您只需要以毫秒为单位存储时间。

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));
    }
}

static

As the other correct answers state, you should not be using static for individual objects (instances). 由于其他正确答案的状态,您不应对单个对象(实例)使用static方法。

The word "static" has a long and twisted history with C and Java, which we can ignore. “静态”一词在C和Java中有着悠久而曲折的历史,我们可以忽略。 The upshot is that, in Java, the word "static" means "not object-oriented". 结果是,在Java中,“静态”一词的意思是“不是面向对象的”。 The word "static" means we want to keep some data ("state") around only once in memory for an entire work session. “静态”一词意味着我们希望在整个工作会话中仅在内存中保留一些数据(“状态”)一次。 With no better place to keep it, we glue that data onto the class' own representation in memory. 没有更好的保留位置,我们将数据粘贴到类在内存中的表示形式。 With a normal object-oriented non-static member variable, each object (instance) has its own piece of data. 使用普通的面向对象的非静态成员变量,每个对象(实例)都有自己的数据。 For Person objects, each Person object has its own firstName and phoneNumber values, while a static variable on Person class would have only one value in memory period. 对于Person对象,每个Person对象都有其自己的firstNamephoneNumber值,而Person类上的静态变量在内存周期中将只有一个值。

Programmers with a background in non-OOP languages may be drawn to static variables, as they seem like global variables. 具有非OOP语言背景的程序员可能会被吸引到static变量,因为它们看起来像全局变量。 Indeed, you could successfully make a Java program entirely of static variables and static methods, with code similar to non-OOP languages. 确实,您可以使用类似于非OOP语言的代码成功地完全用静态变量和静态方法制作Java程序。 But you would miss out on the power and simplicity that OOP brings. 但是您会错过OOP带来的强大功能和简单性。

See the question, What does the 'static' keyword do in a class? 看到问题, “ static”关键字在类中做什么? .

Date-Time Types 日期时间类型

Generally best to use date-time data types when working with date-time data. 通常,在处理日期时间数据时最好使用日期时间数据类型。 Tracking time by milliseconds (count since epoch ) quickly becomes clumsy, confusing, and difficult to debug. 以毫秒为单位的跟踪时间(从epoch开始计数)很快变得笨拙,混乱并且难以调试。 Also, date-time work is surprisingly complicated and tricky. 而且,日期时间工作令人惊讶地复杂且棘手。 Simply search StackOverflow.com for java date to see how complicated date-time work becomes. 只需在StackOverflow.com上搜索java date即可查看日期时间变得多么复杂。

For example, your Question's code mistakenly treats System.currentTimeMillis as time-of-day when actually it is date and time-of-day by counting since the first moment of 1970 in the UTC time zone. 例如,您的Question的代码错误地将System.currentTimeMillis视为一天中的时间,而实际上它是从UTC时区的1970年第一时刻开始计算的,因此它是日期一天中的时间。

You would not handle numbers as bits or text as as octets; 您不会将数字作为位或文本作为八位字节处理; we have defined classes as data types to handle and hide the nitty-gritty details. 我们已经将类定义为数据类型,以处理和隐藏细节。 So you should you date-time classes rather than count-since-epoch. 因此,您应该使用日期时间类而不是count-since-epoch。

Date-Time Libraries 日期时间库

For Java, we have two good date-time libraries: 对于Java,我们有两个很好的日期时间库:

Both have strengths over each other. 两者都有优势。 Fortunately you mix and match both, using whichever is better suited for a particular situation. 幸运的是,您可以混合使用这两种方式,并且更适合特定情况。

Java also has some older classes for date-time work, java.util.Date, java.util.Calendar, java.text.SimpleDateFormat, and others (all outside the java.time package). Java还具有一些用于日期时间工作的较旧的类,java.util.Date,java.util.Calendar,java.text.SimpleDateFormat和其他一些类(均在java.time包之外)。 Unfortunately, these classes are notoriously troublesome, with a confusing history and evolution, and problems in both design and implementation. 不幸的是,这些类非常麻烦,具有令人困惑的历史和发展,以及设计和实现方面的问题。 Avoid them. 避免他们。 They have been supplanted by java.time . 它们已被java.time取代。 Where required, you may convert to-and-from Joda-Time as well as java.time. 在需要的地方,您可以与Joda-Time以及java.time相互转换。

Objects Die 物体死

At the end of the main method your Java program ends. main方法的最后,您的Java程序结束了。 All data in memory is purged, gone. 内存中的所有数据均已清除,消失。 So if you want to store that data longer, you must persist it. 因此,如果您想长时间存储该数据,则必须将其持久化。 Perhaps write a file, or put it into a database. 也许编写文件,或将其放入数据库。

In both your Question's code and the example below, the objects are re-created from scratch each time the program is executed/run. 在您的Question的代码和下面的示例中,每次执行/运行程序时,都会从头开始重新创建对象。 So the objects each get a new date-time. 因此,每个对象都有一个新的日期时间。

Example Code 范例程式码

Here is some example code in Joda-Time 2.4. 这是Joda-Time 2.4中的一些示例代码。

We have an "Animal" class that tracks when its objects are instantiated (get allocated a chunk of memory in which to store its data during runtime). 我们有一个“动物”类,该类跟踪其对象被实例化的时间(在运行时,分配了一块内存来存储其数据)。 That moment is recorded in the member variable "objectCreation" of type DateTime defined in the Joda-Time library. 该时刻记录在Joda-Time库中定义的DateTime类型的成员变量“ objectCreation”中。

Rather than rely implicitly on the JVM's current default time zone, a time zone is assigned. 分配的时区不是隐式依赖于JVM的当前默认时区。 In this case I arbitrarily Nairobi from the list of proper time zone names . 在这种情况下,我会从适当的时区名称列表中任意选择内罗毕。

As an example of using static I created three constants, defining the expected species. 作为使用static的示例,我创建了三个常量,定义了预期的种类。 This is a practical example where we avoid and detect typos such as "dg" for "dog". 这是一个实际的示例,在该示例中,我们避免并检测到“ dog”之类的错字,例如“ dg”。

This example captures the beginning and ending times of execution to show a span of time. 本示例捕获执行的开始和结束时间以显示时间跨度。

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 );
    }

}

When run. 运行时。

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

Naming 命名

Tip: I suggest avoid using the word "package" generically as part of naming your class. 提示:建议您在命名类时避免一般使用“包”一词。 The word package is a keyword used in defining a class as seen in the first line of your Question's code. 单词package是用于定义类的关键字,如您的Question代码的第一行所示。 So mixing "package" into your class name is confusing. 因此,将“包”混入类名中会造成混淆。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM