Reputation: 11
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.
Upvotes: 0
Views: 3317
Reputation: 338406
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?.
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.
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.
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.
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
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.
Upvotes: 0
Reputation: 533492
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));
}
}
Upvotes: 1
Reputation: 39447
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.
Upvotes: 1
Reputation: 11917
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.
Upvotes: 3
Reputation: 3333
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.
Upvotes: 1