Zach Cochran
by Zach Cochran
3 min read

Categories

Tags

Today we’ll take a look at the static keyword and what it does to our fields and methods in our classes.

One of the more daunting things for me coming over to Java was trying to wrap my head around all the types and keywords that the language uses. I remember looking through some of our code at work and seeing private, public, private static, static, private static final, etc, and feeling completely overwhelmed.

Today I got a much better grasp on what exactly a static member of a class does, and why it can be so useful. Hopefully you’ll find this as useful as I did.

As always, the code for this is located in my github repo.

Why static?

When we use the static keyword inside of our class, either on a field or a method, we’re essentially defining constants for a particular class. Static items will belong to all instances of a class, rather than to a specific instance of the class that you instantiate. In other words, fields and methods marked as static will be shared between all instances of a class. Static variables are actually stored in a completely different part of memory than the rest of the variables in the class!

Static Variables

As mentioned above, static variables are going to share a value across all instances of your class. You define a variable as being static by placing the keyword static in front of it at declaration time. You can specifically mark them as either public or private or neither. If you do not chose a specific scope, it looks like they default to a public scope (or maybe whatever the visibility of the class is).

As an added bonus, when the static variable has public visibility (either explicit or implicit), it can be referenced directly from the class object. We’ll see that in an example shortly.

Let’s take a look at a modified version of our Flight class from a few posts back:

public class Flight {

   private int seats = 150, passengers, flightNumber;
   static int allPassengers;

   public Flight() {

   }

   public void add1Passenger() {
       if (seatsAvailable()) {
           this.passengers += 1;
           allPassengers += 1;
       } else {
           handleTooMany();
       }
   }
}

The code above has been modified so that it’s going to increment allPassengers every time that a passenger is added to a fight. So if we were to go ahead and create two flight objects and add some passengers to them, we’d find that the allPassengers parameter is incremented.

   @Test
   public void multiFlightPassengersImplicit() {
       Flight f1 = new Flight();
       f1.add1Passenger();

       Assert.assertEquals(1, Flight.allPassengers);

       Flight f2 = new Flight();
       f2.add1Passenger();

       Assert.assertEquals(2, Flight.allPassengers);
   }

Notice how we can directly reference allPassengers right from the class name, and how each time a new Flight object is created and a passenger is added, the same variable is incremented.

Static Methods

The same type of logic can apply for static methods. The real benefit here again is that you don’t need a specific class instance to call the method. You can instead just call the <class>.<method> directly.

One major thing to note though is that static methods can only access static fields inside their code. They cannot interact with your other instance specific data.

Let’s add in two new methods to our Flight class that will return back allPassengers and allow us to clear them:

   public static int getAllPassengers() {
       return allPassengers;
   }

   public static void clearAllPassengers() {
       allPassengers = 0;
   }

Now what happens if we try to use either of these before a Flight class has even been instantiated?

   @Test
   public void noFlightExists() {
       Assert.assertEquals(0, Flight.getAllPassengers());
       Flight.clearAllPassengers();
       Assert.assertEquals(0, Flight.getAllPassengers());
   }

You can see that this works just fine! Even though we don’t have an instance of Flight created, we can still reference the method directly from the class, and the value is already initialized to 0 for us.

We could also repeat the test from before using our new methods:

   @Test
   public void multiFlightPassengers() {
       Flight f1 = new Flight();
       f1.add1Passenger();
       f1.add1Passenger();

       Assert.assertEquals(2, Flight.getAllPassengers());

       Flight f2 = new Flight();
       f2.add1Passenger();
       f2.add1Passenger();

       Assert.assertEquals(4, Flight.getAllPassengers());

       Flight.clearAllPassengers();

       Assert.assertEquals(0, Flight.getAllPassengers());
   }

And this gives us the same output as before.

Summary

  1. Static variable values will be shared across all instances of a class.
  2. Static variables can only be created at the class level.
  3. Static methods can only access static fields and other static methods.
  4. Static methods cannot be overridden.

💚 A.B.L.