简体   繁体   中英

Java: Setting time of object creation

Java newbie question. 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.

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. 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()

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

2) The constructor makes multiple calls to 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.

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. To fix, remove the keyword static from each of the fields hour, minute and second.

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. 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.

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. 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. 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()
right after creating your object. Try to sleep in between.
Then getTime will print the time from 5 mins ago, not
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.

Maybe this is what you intended, but otherwise, just remove the static keyword from those variables.

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).

The word "static" has a long and twisted history with C and Java, which we can ignore. The upshot is that, in Java, the word "static" means "not object-oriented". 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.

Programmers with a background in non-OOP languages may be drawn to static variables, as they seem like global variables. Indeed, you could successfully make a Java program entirely of static variables and static methods, with code similar to non-OOP languages. But you would miss out on the power and simplicity that OOP brings.

See the question, What does the 'static' keyword do in a class? .

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. Also, date-time work is surprisingly complicated and tricky. Simply search StackOverflow.com for java date to see how complicated date-time work becomes.

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.

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.

Date-Time Libraries

For Java, we have two good date-time libraries:

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). 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 . Where required, you may convert to-and-from Joda-Time as well as java.time.

Objects Die

At the end of the main method your Java program ends. 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. So the objects each get a new date-time.

Example Code

Here is some example code in 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.

Rather than rely implicitly on the JVM's current default time zone, a time zone is assigned. 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. This is a practical example where we avoid and detect typos such as "dg" for "dog".

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. So mixing "package" into your class name is confusing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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