Classes
For Java, all code is part of one class or another. For example, your main program is a class called HelloWorld, and main() is a function within that class. In addition, all of the functions that we have called are part of some other class. For example when we call System.out.println(), println is a function of the class PrintStream of which out is an instance, and out itself is a member of the System class.
However, a class is more than just a collection of functions, it also is a collection of data which those function manipulate. To illustrate how this might work, let’s create a class which can measure elapsed time which we will call Timer.
In general, each class that you create will be in a separate file. To simplify things, we are going to create a static class which will be only used by our HelloWorld class. To do this we declare the class like this:
static class Timer { }
Note that we are declaring this class within our HelloWorld class which will make it accessible to methods defined within this class. This means that the lines above appear inside the curly brackets of the HelloWorld class.
We have also declared the class to be static. We will not get into exactly what this means and why we are using it here except to say that it needs to be static if we wish to create instances of it in our main() function which is also declared static.
Now that we have declared this new class, we can create an instance of it in our main() function as follows:
public static void main(String[] args) { Timer timer = new Timer(); }
Here we have declared a new variable timer which is of type Timer. Note that declaring variables for classes is much like declaring the primitive types. You simply use the class name, followed by the variable name.
As with the primitive types, declaring the variable does not initialize it. To create a new instance of our Timer class use use ‘new Timer()’.
Now we have an instance of the timer, but it currently does not do anything. Since we want it to measure elapsed time, we will need a function to return that time. Let’s name the function GetTime() and have it return the elapsed time in milliseconds. Note that we are going to use a long type for the return value. This is because when we measure time in milliseconds, we might end up with a number that will exceed the maximum size of an int.
static class Timer { public long GetTime() { return(0); } }
At the moment, we are always returning zero, which is not very useful. We are going to need some kind of function that we can call that will return the current time. There are several to choose from, but we are going to use System.currentTimeMillis(). Looking at the documentation for this function, we see that it returns the current system time in milliseconds. However, this is not what we are looking for. What we want is to measure the elapsed time from some event. To do this, we will need to store the current time at the start of the event and then return the difference between the current time and the starting time.
We need to add a member variable to store the starting time:
private long m_startTime = System.currentTimeMillis();
We are making this variable private because we only want our Timer class to have access to it. Notice also that we are also initializing it to the current time. Remember that when you declare variables, they must be initialized at some point before you use them.
Now we can change our GetTime() function to return the elapsed time.
static class Timer { private long m_startTime = System.currentTimeMillis(); public long GetTime() { return(System.currentTimeMillis() - m_startTime); } }
Now when we call the GetTime() function, we will get the elapsed time from the time the Timer object was created. This may not be particularly useful. What we really need is a way to reset the elapsed time back to zero, which we provide by adding a Reset() function:
static class Timer { private long m_startTime = System.currentTimeMillis(); public long GetTime() { return(System.currentTimeMillis() - m_startTime); } public void Reset() { m_startTime = System.currentTimeMillis(); } }
Now we are going to use this new class to print out the message ‘Time Out!” every 2 seconds:
public class HelloWorld { static class Timer { private long m_startTime = System.currentTimeMillis(); public long GetTime() { return(System.currentTimeMillis() - m_startTime); } public void Reset() { m_startTime = System.currentTimeMillis(); } } public static void main(String[] args) { Timer timer = new Timer(); while (true) { if (timer.GetTime() >= 2000) { timer.Reset(); System.out.println("Time Out!"); } } } }
We have created a while loop with the condition set to true. Since ‘true’ is always true, this loop will never end (at least until we stop our program). Then in the loop we check to see if the current elapsed time is greater than or equal to 2000 milliseconds (i.e. 2 seconds), and if it is, we reset the timer back to zero and print our string “Time Out!”.
Run your program and it should print out Time Out! every 2 seconds. Since we are using an infinite loop your program will never finish. However, you can stop it by clicking on the little red square that is right above the console output to the right. Note that you can always use this button to stop any of your programs at any time.
Now the thing that is important to realize is that I can have as many instances of the Timer class as I want, and each instance will have it’s own unique data. For example, I can change our program to use two timers like so:
public class HelloWorld { static class Timer { private long m_startTime = System.currentTimeMillis(); public long GetTime() { return(System.currentTimeMillis() - m_startTime); } public void Reset() { m_startTime = System.currentTimeMillis(); } } public static void main(String[] args) { Timer timer1 = new Timer(); Timer timer2 = new Timer(); while (true) { if (timer1.GetTime() >= 2000) { timer1.Reset(); System.out.println("Timer1"); } if (timer2.GetTime() >= 3000) { timer2.Reset(); System.out.println("Timer2"); } } } }
which will produce output like:
Timer1 Timer2 Timer1 Timer2 Timer1 Timer1 Timer2 Timer1 Timer1 Timer2 Timer1 Timer2 Timer1 Timer1 Timer2 Timer1