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
What kinds of declarations can have private visibility in Java?
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.
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
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.
public void setAge(int age) {
if (!checkAge(age)) { // <---- LINE1 ✓
throw new IllegalArgumentException("invalid age");
} else {
this.age = age; // <---- LINE2 ✓
} // if
} // setAge
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
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.
// 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 |
|
private |
|
|
Y |
Y |
2 |
|
private |
|
|
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.