9.2. Public and Private Visibility

9.2.1. Public Visibility

Instead of saying that something has public visibility, we usually just say that it is public. In Java, only top-level and member-level declarations are allowed to be public. Things that are public are considered to be the most visible; they are always visible.

Visibility

Visible From

Name

Same Class

Same Package

Child Class

Elsewhere

public

Y

Y

Y

Y

  • In Java, the public modifier must be included in a declaration for it to be considered public by the compiler.

  • In UML, the + symbol is used just before a member’s identifier to illustrate that it is public. It is also common practice to assume that a class in a UML class diagram is public if no visibility symbol is included.

  • The javadoc program includes public declarations in a documentation website by default. If you want javadoc to only include public declarations, then the -public command-line argument can be used.

9.2.2. Private Visibility

Instead of saying that something has private visibility, we usually just say that it is private. In Java, only member-level declarations are allowed to be private. Private members are considered the least visible; they are only visible from lines of code in the same class.

Visibility

Visible From

Name

Same Class

Same Package

Child Class

Elsewhere

private

Y

N

N

N

  • In Java, the private modifier must be included in a member’s declaration for it to be considered private by the compiler.

  • In UML, the - symbol is used just before a member’s identifier to illustrate that it is private.

  • The javadoc program does not include private declarations in a documentation website by default; however, they can be included by adding the -private command-line argument (that option will also include anything that is more visible than private — therefore, it will include everything).

Test Yourself

  1. What kinds of declarations can have private visibility in Java?

  2. What is the full javadoc command (not just the option) to generate an API documentation website for a Java package that will result in private declarations being included in the generated website?

9.2.3. Example 1

This is a classic example that many students are familiar with. To get started, let us consider the UML diagram below and the code snippet that follows it.

hide circle
set namespaceSeparator none
skinparam classAttributeIconSize 0

package cs1302.social {

   class Person {
        -name: String
        -age: int

        +<<new>> Person(name: String, age: int)
        +<<new>> Person(other: Person)
        +getName(): String
        +getAge(): int
        +setName(name: String): void
        +setAge(age: int): void
        -checkAge(age: int): boolean
   }
}

Inside Person.java:
public void setAge(int age) {
    if (!checkAge(age)) { // <---- LINE1 ✓
        throw new IllegalArgumentException("invalid age");
    } else {
        this.age = age; // <------ LINE2 ✓
    } // if
} // setAge

On the line labeled LINE1, the code attempts to access checkAge, an instance method of the current object (i.e., it is the same as this.checkAge) declared within the same class. Although that method is private, it is visible from LINE1 because private members are always visible from within the same class. A similar argument can be made for the code on LINE2, which attempts to access the private instance variable age.

Test Yourself

  1. Can you directly access something that is declared private within the same class?

9.2.4. Example 2

According to The Java Language Specification (JLS) 11 Section 6.6 [ACCESS], the developers of Java incorporated visibility into the language “to prevent the users of a package or class from depending on unnecessary details of the implementation of that package or class.”

To illustrate this idea, let’s consider the UML diagram below and the code snippet that follows it.

hide circle
set namespaceSeparator none
skinparam classAttributeIconSize 0

package cs1302.social {
   OtherClass -up-> Person: uses

   class Person {
        -name: String
        -age: int

        +<<new>> Person(name: String, age: int)
        +<<new>> Person(other: Person)
        +getName(): String
        +getAge(): int
        +setName(name: String): void
        +setAge(age: int): void
        -checkAge(age: int): boolean
   }

   class OtherClass {
        +updateAges(persons: Person[]): void
   }

   hide OtherClass fields
}

Inside Person.java:
public void setAge(int age) {
    if (!checkAge(age)) { // <---- LINE1 ✓
        throw new IllegalArgumentException("invalid age");
    } else {
        this.age = age; // <---- LINE2 ✓
    } // if
} // setAge
Inside OtherClass.java:
public void updateAges(Person[] persons) {
    for (int i = 0; i < persons.length; i++) {
        int newAge = persons[i].getAge() + 1;
        if (persons[i].checkAge(newAge)) { // <---- LINE1 ✗
            persons[i].setAge(newAge);
        } // if
    } // for
} // updateAges

On the line labeled LINE1, the code attempts to access the checkAge method, which is an instance method declared within another class. Since that method is private, it is not visible from this line because private members are only visible from within the class where they are declared. If you try to compile OtherClass.java, then you get the following error:

OtherClass.java: error: checkAge() has private access in Person

The error above is exactly what the author of Person wanted to happen. They intended for checkAge to only be used by other methods within the Person class. To make the method not visible from outside the class, they declared it private. Had they declared it public, for example, then the example would have compiled; however, the call to checkAge would add unnecessary redundancy since it is called again inside the call to setAge on the next line (see the previous example for the inside of setAge).

We’re not sure how the author of OtherClass knew about the checkAge method, but the error message lets them know that it is not for them to use. Had they referred to the Javadoc/API documentation for the Person class, it is unlikely that the private method would have been included (private members are not included in the javadoc output by default). If it is private, then it is not for others, and if it is not even listed in the documentation, then that’s less stuff that other programmers need to understand before they’re able to use your code.

Test Yourself

  1. Can you directly access something that is declared private within another class?

9.2.5. Example 3

When first studying visibility, it is common for students to think private is more restrictive than it actually is. Consider the UML diagram below and the code snippet for a copy constructor that follows it.

hide circle
set namespaceSeparator none
skinparam classAttributeIconSize 0

package cs1302.social {

   class Person {
        -name: String
        -age: int

        +<<new>> Person(name: String, age: int)
        +<<new>> Person(other: Person)
        +getName(): String
        +getAge(): int
        +setName(name: String): void
        +setAge(age: int): void
        -checkAge(age: int): boolean
   }
}

// inside Person.java
public Person(Person other) {
    setName(other.name); // <---- LINE1
    setAge(other.age); // <------ LINE2
} // setAge

Test Yourself

On the lines labeled LINE1 and LINE2 above, the code attempts to access the private instance members name and age of the Person object referred to by other. Will LINE1 compile? How about LINE2?

Test Yourself Solution (open after answering the question above)

It does compile!. Although other.name and other.age are private, they’re visible from LINE1 and LINE2 because those lines are in the same class as the declarations.

Remember, private members are always visible from lines in the same class.

The scenario for each line is summarized in the table below.

Member

Accessed

LINE

Name

Declared

In

From

Same Class?

Visible?

1

name

private

Person

Person

Y

Y

2

age

private

Person

Person

Y

Y

While a reference to an object does allow us to find members of the object via .memberName (for some memberName), our ability to access the member from the current location (line of code) depends only on where the member is declared and its visibility. In general, visibility itself has nothing to do with objects; it is all about where the code is written.