Java Static Keyword Example
1. Introduction
In this post, we feature a comprehensive example of the Java Static Keyword. We are also going to see the static variable in Java. Java programming language defines a list of keywords. Here is the static keyword definition from Oracle:
static is a keyword which defines a variable as a class variable. Classes maintain one copy of class variables regardless of how many instances exist of that class. A “static” keyword can also be used to define a method as a class method. Class methods are invoked by the class instead of a specific instance, and can only operate on class variables.
The static variables are loaded during the class-loading process and not collected by the garbage collector. Therefore, the developer should consider the size of static variables to avoid running out of memory.
In this example, I will demonstrate how to:
- Define and use a static variable in a class or in an interface in Java
- Define and use a static method in a class or in an interface in Java
- Define and use a static block in a class
- Define and use a nested static class
2. Technologies Used
The example code in this article was built and run using:
- Java 11
- Maven 3.3.9
- Eclipse Oxygen
- Junit 5.5.2
3. Maven Project
3.1 Dependencies
I will include Junit
in the pom.xml
.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>jcg-zheng-demo</groupId> <artifactId>jcg-static-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <properties> <junit-jupiter.version></junit-jupiter.version> </properties> <build> <sourceDirectory>src/main/java</sourceDirectory> <testSourceDirectory>src/test/java</testSourceDirectory> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> <configuration> <release>11</release> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.5.2</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.5.2</version> <scope>test</scope> </dependency> </dependencies> </project>
3.2 DemoClass
In this step, I will create DemoClass
which has:
- a nested
static
class –DemoStaticClass
. Please note that nested static class can only be created inside a class. It can only access the outer-class’s static attributes and methods. - a
static
String
attribute –commonMsg
- a
static
int
attribute –instanceCount
- two
static
blocks to initialize twostatic
attributes. Please note the static blocks are executed based on its order. - a
static
method –getInstanceCount
() - void
sayHello
() – which creates an object ofDemoStaticClass
and invokes itssaySomething
() method. Please note it can access all the data members and methods inside of nested static class.
DemoClass.java
package jcg.zheng.demo; public class DemoClass { /** * A static class must be created inside a class. * * It can be accessed by outer class name. It can access static data members of * outer class including private. * * It cannot access non-static data members and methods. * * */ static class DemoStaticClass { public DemoStaticClass(int someId) { super(); this.someId = someId; } private static String message = "Static message inside a nested static class"; private int someId; public String saySomething() { return instanceCount + " is from outer-class private static member. " + message + " and " + someId; } } private static String commonMsg; // static members belong to the class, so it's not cleaned by the garbage // collection private static int instanceCount; // static block is executed during the class is loaded in memory static { instanceCount = 0; } // multiple static blocks are executed based on its order static { commonMsg = "Mary likes flowers"; } public static int getInstanceCount() { return instanceCount; } private String name; public DemoClass(String name) { super(); setName(name); instanceCount++; } public String getName() { return name; } public void sayHello() { DemoStaticClass demo = new DemoStaticClass(2); System.out.println(getName() + " " + demo.saySomething() + commonMsg); } public void setName(String name) { this.name = name; } }
- line 15 – create a nested static class
- line 21, 31, 35 – create static data members
- line 38, 43 – initialize static data member values
- line 47 – create a static method
- line 65 – create an object of a nested static class
3.3 DemoInterface
In this step, I will create DemoInterface
which has two static members: one with a static keyword, the other doesn’t. It also has a static
method. Interface does not allow a static block.
DemoInterface.java
package jcg.zheng.demo; public interface DemoInterface { String defaultStaticV = "test"; static String message = "I am awesome!"; static String foo(String msg) { return "Static is useful! " + msg; } }
3.4 Task
In this step, I will create a Task
class which implements Runnable
. It has a static count
member.
Task.java
package jcg.zheng.demo; public class Task implements Runnable { private static int count; private int taskId; public Task(int id) { this.taskId = id; count++; } @Override public void run() { System.out.println(Thread.currentThread().getName() + " Task ID : " + this.taskId + " static " + count); } }
4. JUnit Test
4.1 DemoClassTest
In this step, I will create DemoClassTest
which has the following tests:
test_nested_static_class
– creates an instance ofDemoStaticClass
and uses itssaySomething
method.test_static_method
– create 10 instances ofDemoClass
and prints out its static attribute –instanceCount
test_static_methods
– repeatedly calling the static method 10 times and got the same result.
DemoClassTest.java
package jcg.zheng.demo; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.Test; public class DemoClassTest { private DemoClass dClass; @Test public void test_static_method() { assertEquals(0, DemoClass.getInstanceCount()); for (int i = 1; i < 10; i++) { dClass = new DemoClass("Mary" + i); assertEquals("Mary" + i, dClass.getName()); assertEquals(i, DemoClass.getInstanceCount()); dClass.sayHello(); } } @RepeatedTest(10) public void test_static_methods() { assertEquals(0, DemoClass.getInstanceCount()); } @Test public void test_nested_static_class() { DemoClass.DemoStaticClass nestedCls = new DemoClass.DemoStaticClass(); assertEquals("0 instances of DemoClass. Mary is great and Mary likes flowers", nestedCls.saySomething()); } }
Execute the tests and capture the output here.
Running jcg.zheng.demo.DemoClassTest Mary1 1 is from outer-class private static member. Static message inside a nested static class and 2Mary likes flowers Mary2 2 is from outer-class private static member. Static message inside a nested static class and 2Mary likes flowers Mary3 3 is from outer-class private static member. Static message inside a nested static class and 2Mary likes flowers Mary4 4 is from outer-class private static member. Static message inside a nested static class and 2Mary likes flowers Mary5 5 is from outer-class private static member. Static message inside a nested static class and 2Mary likes flowers Mary6 6 is from outer-class private static member. Static message inside a nested static class and 2Mary likes flowers Mary7 7 is from outer-class private static member. Static message inside a nested static class and 2Mary likes flowers Mary8 8 is from outer-class private static member. Static message inside a nested static class and 2Mary likes flowers Mary9 9 is from outer-class private static member. Static message inside a nested static class and 2Mary likes flowers Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.197 sec
4.2 DemoInterfaceTest
In this step, I will create DemoInterfaceTest
which tests the two static members and a static method.
DemoInterfaceTest.java
package jcg.zheng.demo; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; public class DemoInterfaceTest { @Test public void test_static() { assertEquals("I am awesome!", DemoInterface.message); assertEquals("test", DemoInterface.defaultStaticV); assertEquals("Static is useful! test", DemoInterface.foo("test")); } }
Execute tests and capture output.
Running jcg.zheng.demo.DemoInterfaceTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.001 sec
4.3 MultiThreadsTest
In this step, I will create a MultiThreadTest
class which creates ten threads to execute the Task
Runnable. You will see that the Task
‘s static count value is not matching the total instance count.
MultiThreadsTest.java
package jcg.zheng.demo; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.IntStream; import org.junit.jupiter.api.Test; public class MultiThreadsTest { @Test public void test_multi_thread_on_static() { ExecutorService service = Executors.newFixedThreadPool(10); IntStream.range(0, 10).forEach(i -> service.submit(new Task(i))); } }
Execute tests and capture output here.
pool-1-thread-9 Task ID : 8 static 10 pool-1-thread-8 Task ID : 7 static 10 pool-1-thread-7 Task ID : 6 static 8 pool-1-thread-2 Task ID : 1 static 4 pool-1-thread-6 Task ID : 5 static 8 pool-1-thread-5 Task ID : 4 static 10 pool-1-thread-1 Task ID : 0 static 4 pool-1-thread-10 Task ID : 9 static 10 pool-1-thread-4 Task ID : 3 static 7 pool-1-thread-3 Task ID : 2 static 4
As you seen here, the static instanceCount
is not coordinating with the object count for each thread execution.
5. Java Static Keyword Summary
As you seen in this example, I demonstrated:
- How to define and use a static member|method in a class and interface.
- How the static block is executed in a class.
- How to import static method from the Junit library.
- How a multi-threads application may give you unexpected results when calling a static method.
Developer should be careful when creating a large size static variable as it’s not cleaned up by the garbage collector. Developer also considers when creating a static method as it’s not easy to write a unit test. Please read this article for pro and con on static methods.
6. Download the Source Code
You can download the full source code of this example here: Java Static Keyword Example