Chapter 5 - Java for Beginners Course

Access Level Modifiers

Java provides us with 4 different levels of access for classes and members of a class that allow us to restrict their usage from other classes.

Access modifier keywords

There are 3 keywords introduced by Java to specify the 4 access levels that we want to provide. Two of these we’ve seen in examples in previous chapters, public and private.

  • public is the most permissive access level, meaning that a class or member is accessible by all other classes in our application.

  • private is the least permissive access level, meaning that a class member is only accessible by the class that contains it.

The other 2 access modifiers that Java provides are:

  • protected meaning that a class member is only accessible by the class that contains it, subclasses of it and other classes in the same package.

  • The default access level means that a class member is only accessible by the class that contains it and other classes in the same package. In contrast to protected, subclasses can’t access these class members.

The default access level is used when none of the other 3 modifiers are used. Hence there is no keyword associated with it.

The following table is a good summary of what classes have visibility over classes/fields/methods with a given level of visibility.

Modifier Owning Class Class in Same Package Sub-class of Owning Class Any other class

public

Yes

Yes

Yes

Yes

protected

Yes

Yes

Yes

No

default (no keyword)

Yes

Yes

No

No

private

Yes

No

No

No

We’ll cover the concept of subclasses when we cover Inheritance later in this chapter.

Access level modifiers for classes

Top-level classes can only be defined as public or default access, meaning that they are either visible to all other classes in the application (public), or only to classes in the same package (default).

Nested classes, which we haven’t covered yet, can actually have any of the 4 modifiers we defined above. Nested classes are classes defined inside other classes and will be covered in a further chapter.

Top-level classes are classes that aren’t nested, i.e., they aren’t defined inside other classes. All of the examples we’ve seen so far are of top-level classes.

Access level modifiers for class members

As we’ve seen in previous examples, we can define access level modifiers for the fields and methods in our classes and we can use any of the 4 levels mentioned above.

Example

Let’s assume we define a Game class with different access levels for multiple fields and methods:

package io.jcoder.tutorials.ch05.accesslevels;

public class Game {
    private String title;

    private int maxPlayers;

    private boolean titleDefined;

    public void initialize() {
        title = "Unnamed Game";
        maxPlayers = 0;
        titleDefined = false;
    }

    public void setTitle(String gameTitle) {
        titleDefined = true;
        title = gameTitle;
    }

    protected void setMaxPlayers(int gameMaxPlayers) {
        maxPlayers = gameMaxPlayers;
    }

    void printDetails() {
        System.out.println("Game is: " + title + " with max players: " + maxPlayers + " - Title Set: " + titleDefined);
    }

}

Our example Game class actually defines its state as all private (all its fields are marked as private), and its methods with different levels of access.

As expected, the fields can be accessed from inside the Game class even though they are marked as private as they are owned by this class. The Game class is allowed to read/modify their values, like we do in the initialize() method.

Now, let’s invoke these methods from a different class. Let’s define a JavaAccessLevelApp in our code. For the purpose of the example, make sure it is created in the same package as our Game class above.

package io.jcoder.tutorials.ch05.accesslevels;

public class JavaAccessLevelApp {

    public static void main(String[] args) {
        // Our Game class is defined as public hence we can access it from all classes (including this one)
        Game sampleGame = new Game();

        // The initialize method is defined as public, hence we can invoke it from this class
        sampleGame.initialize();

        // The printDetails method is actually default level, but as this class (JavaAccessLevelApp) lives on the same
        // package, we can make use of it
        sampleGame.printDetails();

        // The setTitle method is public so it's accessible from all classes
        // The setMaxPlayers, even though it is protected, this class (JavaAccessLevelApp) lives on the same package
        // so we can make use of it as well
        sampleGame.setTitle("Chess");
        sampleGame.setMaxPlayers(2);

        // If you uncomment the lines below, you should see the compiler error and IDE suggestions about what is going
        // on. These fields are not visible/accessible from this class as they are defined as private
        // sampleGame.title = "Another Game Name";
        // sampleGame.maxPlayers = 2;

        sampleGame.printDetails();
    }

}

Output:

Game is: Unnamed Game with max players: 0 - Title Set: false
Game is: Chess with max players: 2 - Title Set: true
Try uncommenting the 2 lines mentioned in the example above and see what compilation errors you get. Try also moving the JavaAccessLevelApp class into a different package. See what compilation errors you get.