9.3. Package Private Visibility

Instead of saying that something has package private visibility, we usually just say that it’s package private. In Java, only top-level and member-level declarations are allowed to be package private. Entities that are package private are slightly more visible than entities that are private; they are only visible from lines of code in the same package.

Visibility

Visible From

Name

Same Class

Same Package

Child Class

Elsewhere

package private

Y

Y

N

N

  • In Java, there is no modifier keyword for package private visibility. For top-level declarations and member-level declarations within a class, the omission of a visibility modifier will cause the compiler to treat the declared thing as package private. This behavior is different for member-level declarations within an interface, where the omission of a visibility modifier defaults a declaration’s visibility to public.

  • In UML, the ~ symbol is used just before an identifier to illustrate that it is package private. Some UML programs may not support displaying the visibility for top-level declarations; in those cases, a quick hack is to include the ~ as part of the name. Although omitting a visibility modifier in Java code may default to package private, the same is not true for UML class diagrams; they default to public visibility (covered in a later section).

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

Some people refer to package private visibility as the “default visibility” because a modifier isn’t needed to indicate that certain declarations are package private; however, the term “default” should be avoided when describing visibility so that the concept is not confused with Java’s default member-level visibility for interfaces or a completely unrelated concept of default methods in interfaces, the latter being something that is not covered in this text.

Test Yourself

  1. What visibility keyword is used in Java to denote that a declaration is package private?

Review Question

Consider the following directory structure for a project:

cs1302/
├─ models/
│  ├─ Utility.java
│  └─ Person.java
├─ store/
│  └─ Driver.java
└─ main/
   └─ App.java
  1. Write the package statements that should appear at the top of each file.

    Solution
    // Utility.java and Person.java
    package cs1302.models;
    
    // Driver.java
    package cs1302.store;
    
    // App.java
    package cs1302.main;
    
  2. Which classes are in the same package?

    Solution

    Same package: Utility.java and Person.java (cs1302.models).

  3. Utility.java has no visibility modifier (package private). Which files can directly access the entities declared within Utility?

    Solution

    Only Person.java (same package cs1302.models) can access Utility directly. Driver.java and App.java cannot.

  4. Person.java has a private instance variable private String name;. Can Driver.java or App.java access name directly? Why or why not?

    Solution

    No. name is private, so it is only accessible within Person.java itself. No external class can access it directly, regardless of package.

  5. If a method in Utility.java is declared private, can any other class in cs1302.models call it? What about a class in cs1302.store?

    Solution

    Since its a private method, it is only accessible within Utility.java. Classes in cs1302.models or cs1302.store cannot call it.

  6. Suppose you accidentally declare Person as public instead of package private. Which new classes can now access it directly that could not before?

    Solution

    Declaring Person as public allows all classes in all packages (cs1302.store, cs1302.main) to access it directly.

  7. If Utility has a private constructor and only static methods, what is the purpose of making the constructor private? Could Driver.java create a new Utility object? Why or why not?

    Solution

    Private constructor prevents object creation outside the class. Driver.java cannot create a new Utility object; only the class itself can call its constructor (useful for utility classes with static methods).

  8. For App.java in cs1302.main, which of the following statements are true?

    1. It can directly access package private members of Utility.java.

    2. It can call public static methods of Utility.java if it’s imported.

    3. It can access private members of Person.java after creating an object.

    Solution
    1. False – package private not visible outside package.

    2. True – public static methods can be called if class is imported.

    3. False – private members cannot be accessed directly even after object creation.

9.3.1. Example 1

Here is our first example involving a top-level declaration. To get started, let’s consider the UML diagram below and the two code snippets that follow it.

NOTE: class Utility is package private. Unfortunately, the ~ is not showing up properly in the diagram.

hide circle
set namespaceSeparator none
skinparam classAttributeIconSize 0

package cs1302.models {

   ~class Utility {
        -<<new>> Utility()
        +min(a: double, b: double): double
   }

   hide Utility fields
}

package cs1302.store {
   class Driver {
      +main(args: String[]): void)
   }

   hide Driver fields
}

Driver -left-> Utility: uses

Listing 9.7 Inside Utility.java:
package cs1302.models;

class Utility { // <---- LINE1
    // ... rest omitted
Listing 9.8 Inside Driver.java:
package cs1302.store;

import cs1302.models.Utility; // <---- LINE2

// ... rest omitted

On the line labeled LINE1, the author omitted a visibility modifier in their top-level declaration of the Utility class. As discussed earlier, this causes the class to default to package private visibility. On LINE2, which exists in Driver.java in a different package [6], an attempt is made to import the Utility class. Since that class is package private, it’s not visible from this line because things that are package private are only visible from within the same package. If you try to compile Driver.java, then you get the following error:

Driver.java: Utility is not public in cs1302.models; cannot be accessed from outside package

The error above is exactly what the author of Utility class wanted to happen. They intended for Utility itself to only be used by code residing within the cs1302.models package. To make the method not visible from outside the package, they omitted a visibility modifier in the top-level class declaration. Had they declared it public, for example, then the example would have compiled.

As an aside, the UML diagram for this example also includes a private constructor [7]! You can read about it in the footnote.

Test Yourself

  1. When are two classes considered to be in the same package?

  2. When are two classes considered to be in different packages?

9.3.2. Example 2

In this example, we’ll see how package private visibility can be used at the member-level for access control. Suppose a factory has a contract with a store to produce some product. Throughout the year, the store may need to request changes to its contract based on sales, buyer interest, etc. The driver program on the factory’s side should be able to access methods to request, approve, and deny contract-related changes; however, the overall class design should not allow for the store to approve or deny changes in this scenario. To see how we can utilize package private visibility to accomplish this, let’s consider the UML diagram below and the two code snippets that follow it.

hide circle
set namespaceSeparator none
skinparam classAttributeIconSize 0

package cs1302.factory {

   FactoryDriver -up-> Factory: uses
   class Factory {
        +requestChange(message: String): void
        ~approveChange(message: String): void
        ~denyChange(message: String): void
   }
   class FactoryDriver {
        +main(args: String[]): void)
   }

   hide Factory fields
   hide FactoryDriver fields
}

package cs1302.store {
   class Driver {
      +main(args: String[]): void)
   }

   hide Driver fields
}

Driver -left-> Factory: uses

Listing 9.9 Inside FactoryDriver.java (cs1302.factory package)
public static void main(String[] args) {
    Factory factory = new Factory();
    factory.requestChange("decrease price"); // <------- LINE1
    factory.approveChange("decrease price"); // <------- LINE2
    factory.denyChange("decrease price"); // <---------- LINE3
} // main
Listing 9.10 Inside Driver.java (cs1302.store package)
public static void main(String[] args) {
    Factory factory = new Factory();
    factory.requestChange("increase quantity"); // <---- LINE4
    factory.approveChange("increase quantity"); // <---- LINE5
    factory.denyChange("increase quantity"); // <------- LINE6
} // main

The lines labeled LINE1, LINE2, and LINE3 each attempt to access a different member of the Factory class from the same package. The table below summarizes the scenario for each line. Class names in the In and From columns have been omitted since they’re not relevant for this particular example.

Member Accessed

LINE

Name

Declared

In

From

Visible?

1

requestChange

public

cs1302.factory

cs1302.factory

Y

2

approveChange

package private

cs1302.factory

cs1302.factory

Y

3

denyChange

package private

cs1302.factory

cs1302.factory

Y

Likewise, the lines labeled LINE4, LINE5, and LINE6 each attempt to access a different member of the Factory class from a different package. The table below summarizes the scenario for each line.

Member Accessed

LINE

Name

Declared

In

From

Visible?

4

requestChange

public

cs1302.factory

cs1302.store

Y

5

approveChange

package private

cs1302.factory

cs1302.store

N

6

denyChange

package private

cs1302.factory

cs1302.store

N

If you try to compile Driver.java as written, then you get the following error:

Driver.java: error: approveChange(String) is not public in Factory; cannot be accessed from outside package

Through careful use of visibility, the author of the Factory class was able to achieve the access control described near the beginning of this example. That is, code within the cs1302.factory package can request, approve, and deny contract-related requests, while code in other packages can only request changes. It’s a beautiful, simple setup, but it did require the author to understand package private visibility.

In the error message that was recently discussed, the wording “is not public in” may lead you to believe that only public members are visible from another package; that’s not the case. We’ll provide an example in the next section on protected visibility that illustrates this.

Test Yourself

  1. How can package private visibility be used to limit where the creation of objects takes place?