Last updated on April 8, 2013
One of the things that confuse people trying to learn Java is static fields and methods. Although the use of static keyword is very simple, it is easy for beginners to get confused while studying ‘static’. In this article we will look into details of static keyword and clarify the points that confuse developers.
Class and Object Variables
As you know, fields are created separately in memory for each instance of a class. If you have a class including name, surname and age variables, then all these variables will be created and valued separately for each instance of the class. This type of variables are named as “object variables” because they belong to a specific object. In Java, there are also variables that belong to a class rather than an object. That’s where static keyword comes into play.
Variables defined by using static keyword are named “class variables”. This kind of variables hold values related to a class, not to a specific object and they occupy space in memory even if there is no existing object created from that class. On the other hand, object variables are created along with an actual object. Another difference between object and class variables is that there is only one instance of a class variable no matter how many objects are created. Lets take a look at the code sample below:
package com.seckintozlu.article; public class Student{ private String name; // Object variable private int age; // Object variable private String studentId; // Object variable public static int numberOfStudents = 0; // Class variable public Student(String name, int age, String studentId) { this.name= name; this.age= age; this.studentId= studentId; // Increase the number of students whenever an object is created numberOfStudents++; } }
Here we have 3 object variables and a class variable, in constructor we are increasing value of the class variable whenever an object is created. Now lets see the code below:
package com.seckintozlu.article; public class Program { public static void main(String args[]) { System.out.println("Number of student in the beginning: " + Student.numberOfStudents); // create two student objects Student student1 = new Student("Obi-Wan Kenobi", 19, "2010001"); Student student2 = new Student("Anakin Skywalker", 16, "2010002"); int num = Student.numberOfStudents; System.out.println("Number of students (Using class name): " + num ); num = student1.numberOfStudents; System.out.println("Number of students (Using first object): " + num ); num = student2.numberOfStudents; System.out.println("Number of students (Using second object): " + num ); } }
This code piece is going to produce the result below:
Number of student in the beginning: 0 Number of students (Using class name): 2 Number of students (Using first object): 2 Number of students (Using second object): 2
The first line of the result is 0 because we are printing out the value of the static variable before we create any object. We are able to do this because like I mentioned before static variables are created in memory even if we do not have any object. In the following lines we are creating two objects which increase the value of the static variable to 2. Then, we are printing out the static variable again using class name and two object references separately. Static variables can be accessed through class name or object references but we get the same result in each case because there is only one instance of a class variable and they all point to that. Object variables get created for each object separately but static variables are created only once and they exist even if we do not have any object.
Static Methods
Now lets take a look at how we use static keyword with methods. Normally, when you need to invoke a method you simply create an object and invoke the method using the object reference. However, as for variables, it is possible to create methods that are independent of objects. We do not need to create an object to invoke static methods. We can simply use the class name to do that. Lets look at the code below.
package com.seckintozlu.article; public class Student { private String name; // Object variable private int age; // Object variable private String studentId; // Object variable private static int numberOfStudents = 0; // Class variable public Student(String name, int age, String studentId) { this.name= name; this.age= age; this.studentId= studentId; // Increase the number of students whenever an object is created numberOfStudents ++; } public static int getNumberOfStudents () { return numberOfStudents ; } }
The difference of this code from the previous Student class is only a new static method. We were referencing the public class variable numberOfStudents using its name in the first example, but this time we made the class variable private and we are using a public static method to point to that. To test this code we will use the following:
package com.seckintozlu.article; public class Program { public static void main(String args[]) { System.out.println("Number of students in the beginning: " + Student.getNumberOfStudents()); // Create two student object Student student1 = new Student("Obi-Wan Kenobi", 19, "2010001"); Student student2 = new Student("Anakin Skywalker", 16, "2010002"); int numberOfStudents = Student.getNumberOfStudents(); System.out.println("Number of students: " + numberOfStudents); } }
This code will generate the following output:
Number of students in the beginning: 0 Number of students: 2
Because getNumberOfStudents method is static, it is possible to invoke it without creating an object from Student class. If you already have an object created from Student class, you can use the object reference to call getNumberOfStudents (or any static method) but it is recommended to use class name for readibility. Likewise, while accessing the static variables, we can use object references as well but it will make your code less readable.
The most important thing to know about static methods is this: We cannot reference to a non-static element within a static method. If the numberOfStudents field in our example were not a static variable, we would get an error message at compile time. Also, we cannot invoke non-static methods within static methods. Lets give an example:
package com.seckintozlu.article; public class Student{ private String name; // Object variable private int age; // Object variable private String studentId; // Object variable private static int numberOfStudents = 0; // Class variable public Student(String name, int age, String studentId) { this.name = name; this.age = age; this.studentId = studentId; // Increase the number of students whenever an object is created numberOfStudents++; } public int findNumberOfStudents() { return numberOfStudents; } public static int getNumberOfStudents() { return findNumberOfStudents(); } }
We added a new non-static method named findNumberOfStudents to the Student class. It only returns the value of numberOfStudents variable. Please pay attention here: we cannot reference a non-static element within a static method. But here we are doing the reverse, we are accessing a static field in a non-static method which is perfectly valid. However, static getNumberOfStudents method is trying to invoke findNumberOfStudents which is not static. This is not valid based on the static access rule we have just mentioned. When we try to compile this class, we will get an error like this: “Cannot make a static reference to the non-static method findNumberOfStudents() from the type Student” We would get the same error message if we tried to reference to a non-static field. (e.g “name”)
Let me try to explain the reason behind this rule. We know that static variables and methods are independent of objects. This means that we can invoke static methods and assign values to static variables even if there is no object created. However, non-static elements can exist only when an object is created. Based on this, if we try to reference a non-static variable inside a static method, how do we know that which object’s field we are referencing to? At that moment, there might be no object at all. This statement is also true when we invoke a non-static method inside a static method. For this reason, we can only reference static elements inside static methods. But, we can reference static elements from non-static methods because static elements had already been created before any object.
When we get the error message while trying to invoke a non-static method within a static one, making the other method also static will work but this might not be a good idea. If you end up creating a lot of static methods then stop and think whether your methods need to be static or not. We will touch on this in the end of the article. Now lets see another usage of static keyword.
Static Code Blocks
Static code clocks are used for assigning initial values to static variables. These are also called “static initializers”. Static blocks are executed right after static variables are loaded into the memory. JVM guarantees that static code blocks are executed before an object created for that class.
package com.seckintozlu.article; import java.util.Random; public class StaticInitializer { private static int array[]; private static int length = 10; static { array = new int[length]; Random rnd = new Random(); for(int i=0; i < length; i++) array[i] = rnd.nextInt(100); } }
Looking at the code above, we are creating an array of integers with randomly assigned values. With the static code block, the array is filled with random integers as soon as “array” variable is created. One more thing, we cannot access non-static elements inside static code blocks as well. I do not want to go into more detail since static blocks are not used quite often.
Static Import
We already know that we reference static methods using the class name. For example in Java, Math class in java.lang package is full of static methods and we need to invoke these methods using Math.nameOfMethod(). Using static import we can invoke them by using method name only. Lets see how it is used:
package com.seckintozlu.article; import static java.lang.Math.*; public class Program { public static void main(String args[]) { System.out.println("Square root 25: " + sqrt(25)); System.out.println("Log(100): " + log(100)); System.out.println("Pi: " + PI); } }
As you see in the code, when we put static import in our code, we can reference static methods and variables without using the class name. Normally we would use Math.sqrt() and Math.PI if we did not have static import.
When to Use Static Variables?
Making the decision of using a class variable or an object variable might confuse people who has just started programming in Java or any other language that has “static” feature. Actually, the difference is really obvious. Class variables (statics) are common for each object of that class and there is only one instance of it. On the other hand, object variables belong to an object and its value varies depending on the object itself. In the first example of student class I gave in the beginning, you can easily tell that each Student object has to have a separate values for variables like name and studentId.
On the other side, since numberOfStudents variable holds the number of student objects that are created, it has to have a single value. In other words it needs to be a static variable. We can store it as an object variable but in that case each object will have a separate copy and we will need to update all of them when its value changes. As you can tell it is not an appropriate way of handling this.
When to Use Static Methods?
This is a more difficult question than the previous one. In object-oriented programming languages, objects possess behaviors and state. The variables we have specifies the state, and methods represents the behavior. If a method is dependent on state of the object, or if it is affected by it, then that method needs to be an object method (non-static). If it is completely independent of the state, in other words if state of the object does not affect the result the method will generate, then we can define it as a static method.
As an example, all the methods in java.lang.Math are static. In order to calculate square root of a number, we just need to pass the number to the method as a parameter. The state of an object that will be created from Math class has nothing to do with square root calculation of a number. So, we do not need to create an object to calculate a square root. You might struggle finding an example this obvious while developing but knowing the difference will help you find the answer.
The last note: public static void main(String args[])
In Java, signature of main method is pre-defined. Main method has to be public and static. It has to be public because JVM needs to be able invoke it from outside. It also has to be static because JVM does not instantiate the class where main method resides. To be able to invoke a method without creating an object, it has to be defined static.