Explanation of the Java access modifiers

This is another topic which seems to be under-explained in the set of tutorials I’m following: access modifiers. These are “public”, “protected”, and “private” (as well as the “default” access, which doesn’t need to be written explicitly). In one of the tutorials, there is a piece of code which looks like:

public class InstanceCounter {

  private static int numInstances = 0;

  protected static int getCount(){
    return numInstances;
  }

  private static void addInstance(){
    ++numInstances;
  }

  InstanceCounter(){
    InstanceCounter.addInstance();
  }

  public static void main(String args[]){
    System.out.println("Starting with " + InstanceCounter.getCount() + " instances.");

    for(int i = 0; i < 500; ++i){
      new InstanceCounter();
    }
    System.out.println("Created: " + InstanceCounter.getCount() + " instances.");
  }
}

where line 5 shows a private static int function called getCount() and line 9 shows a private static void function called addInstance()getCount() returns an integer (hence the int), but what does private mean? Or static? And why should addInstance() be private when getCount() is protected?

Java access modifiers determine “who” can see and use variables and methods. Public variables and methods can be used anywhere, by anyone. Protected variables and methods can only be used within the package in which they are defined, and through inheritance. By default, variables and methods with no additional access specifier are available only within the package in which they are defined. And private variables and methods are available only within the class in which they’re defined.

Essentially, each access modifier increases the accessibility of variables and methods within a class. Since, in Java, everything is a class, packages (equivalent to header files in C++) contain one or more classes. Variables and methods defined within those classes can be available to those classes only (private); available to the package in which they are defined (default); available to additional, external classes through inheritance (protected); or available to any program which imports the package (public).

In the code above, then, addInstance() is available only to the InstanceCounter class. If we were to create a second class which extended InstanceCounter, it would not be able to access addInstance(), though it would be able to execute getCount(). For instance, the following is perfectly acceptable Java code:


public class InstanceCounter {

  private static int numInstances = 0;

  protected static int getCount(){
    return numInstances;
  }

  private static void addInstance(){
    ++numInstances;
  }

  InstanceCounter(){
    InstanceCounter.addInstance();
  }

  public static void main(String args[]){
    System.out.println("Starting with " + Extension.getCount() + " instances.");

    for(int i = 0; i < 500; ++i){
      new InstanceCounter();
    }
    System.out.println("Created: " + InstanceCounter.getCount() + " instances.");
  }

}

class Extension extends InstanceCounter {
  Extension(){} // blank constructor
} 

Advertisements