9. Visibility Lesson

Visibility

Visibility

Lesson Objectives

Introduce visibility using UML diagrams that illustrate a code base that starts small and gets larger over time. In each part, we will introduce one of Java’s four visibility options by incorporating it into one or places in the code base, then explore the impact of those changes.

Part 1: Getting Started
Rapid Fire Review
  1. For each line marked with a comment below, write down whether each entity declaration is a top-level, member-level, or local-level declaration.

     1package cs1302.social;
     2
     3public class Person { // <------------------------- LINE1
     4
     5   private String name; // <----------------------- LINE2
     6
     7   public Person(String name) { // <--------------- LINE3
     8      int x = 42; // <----------------------------- LINE4
     9      setName(name);
    10   } // Person
    11
    12   public String getName() { // <------------------ LINE5
    13      return name;
    14   } // getName
    15
    16   protected void setName(String name) { // <------ LINE6
    17      this.name = name;                 // <------- LINE7
    18   } // getName
    19
    20} // Person
    
  2. In the table below, replace each ? with a Yes/No indicating where each entity declaration is visible from.

    Entity

    Visible From

    Declared As

    Same Class

    Same Package

    Child Class

    Elsewhere

    public

    ?

    ?

    ?

    ?

    protected

    ?

    ?

    ?

    ?

    package private

    ?

    ?

    ?

    ?

    private

    ?

    ?

    ?

    ?

Why Visibility?

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.”

Why Visibility?
  • How does visibility relate to encapsulation?

  • How might visibility relate to security?

  • Who benefits from visibility?

Evolving UML

!includesub lesson9.common.puml!VERSION_1

  • How many classes are depicted?

  • How many packages are depicted?

  • How many public entities do you see?

  • How many protected entities do you see?

  • How many package private entities do you see?

  • How many private entities do you see?

!includesub lesson9.common.puml!VERSION_2

  • How many classes are depicted?

  • How many packages are depicted?

  • How many public entities do you see?

  • How many protected entities do you see?

  • How many package private entities do you see?

  • How many private entities do you see?

  • For each package private entity you see, explain why you believe the developers made the decision to make those entities package private.

!includesub lesson9.common.puml!VERSION_3
!includesub lesson9.common.puml!CS1302_UTIL_SHORT

  • How many classes, interfaces, or enums are depicted?

  • How many packages are depicted?

  • Do you see any public entities?

  • Do you see any protected entities?

  • Do you see any package private entities?

  • Do you see any private entities?

  • For each package private entity you see, explain why you believe the developers made the decision to make those entities package private.

  • What does the Utility class look like?

  • Is a Utility object required to call its static methods?

  • Why isn’t Utility currently being used?

Utility Class Declaration
Listing 75 In Utility.java
1package cs1302.util;
2
3class Utility {
4
5    private Utility() {}
6
7    ...
8
9} // Utility
Part 2: Book
Book Copy Constructor

!includesub lesson9.common.puml!VERSION_3

System.currentTimeMillis()

System and System.currentTimeMillis are both public, and calling System.currentTimeMillis() is a valid call from anywhere that will return with a long value representing the current time. In the examples here, we use it to make serial numbers; however, other approaches are probably more appropriate in practice.

ACTIVITY: For each potential copy constructor shown below, indicate if it is valid (will compile) or invalid (will not compile) – if it is invalid, then write down why:

Listing 76 Book(Book) Version 1
1public Book(Book other) {
2    super(System.currentTimeMillis());
3    this.setTitle(other.title);
4} // Book
Listing 77 Book(Book) Version 2
1public Book(Book other) {
2    super();
3    this.title = other.title;
4    this.serial = System.currentTimeMillis();
5} // Book
Listing 78 Book(Book) Version 3
1public Book(Book other) {
2    super();
3    this.title = other.title;
4    this.setSerial(other.getSerial());
5} // Book
Solution
  1. Version 1: Will not compile because the Product constructor does not take any arguments. When we pass an argument to super, the compiler will not be able to find that constructor.

  2. Version 2: The first two lines will work as expected. However, the serial instance variable in Product cannot be accessed directly from within the Book class because it is package private.

  3. Version 3: This compiles and properly initializes both instance variables in the Book object.

Code Interpretation

!includesub lesson9.common.puml!VERSION_3

ACTIVITY: Each of the following lines are already in BookDriver. for each line below, copy it down, then indicate if it is valid (will compile) or invalid (will not compile) – if it is invalid, then write down why:

Listing 79 Assume this code is in BookDriver.main.
1Book b = new Book("Lord of the Rings");
2InventoryManager im = new InventoryManager();
3System.out.println(b);
4b.setTitle("The Great Gatsby");
5InventoryManager.nullCheck("main", b);
6im.addItem(b);
7im.requestPurchase(b);
8im.search(b);
9im.approvePurchase(b);
Solution
  1. Valid

  2. Invalid: the InventoryManager constructor is private in the InventoryManager class.

  3. Valid

  4. Invalid: the setTitle method is private in the Book class.

  5. Invalid: the nullCheck method is private in the InventoryManager class.

  6. Invalid. The addItem method is package private in the InventoryManager class.

  7. Valid

  8. Valid

  9. Invalid. The approvePurchase method is package private in the InventoryManager class.

Discussion

If we moved the code in the previous activity to InventoryDriver, would our answers be the same?

Solution

Lines 6 and 9 would be valid in this scenario because they would be able to access package private methods in the cs1302.inventory package.

Part 3: InventoryDriver
Code Interpretation 1

!includesub lesson9.common.puml!VERSION_3

ACTIVITY: Each of the following lines are already in InventoryDriver. for each line below, copy it down, then indicate if it is valid (will compile) or invalid (will not compile) – if it is invalid, then write down why:

Listing 80 Assume this code is in InventoryDriver.main.
1Book b = new Book("Lord of the Rings");
2b.setTitle("1984");
3System.out.println(b.getTitle());
4Product p = new Book("The Great Gatsby");
5System.out.println(p.getTitle());
6System.out.println(p);
7p.setSerial(14);
8p.serial = 14;
Solution
  1. Valid

  2. Invalid: the setTitle method is private in the Book class.

  3. Valid

  4. Valid

  5. Invalid: the getTitle method cannot be called on a reference of type Product since Product does not contain that method. While this is invalid, the reason is not related to visibility.

  6. Valid

  7. Valid

  8. Valid

Bonus Practice: How would the answers change if we moved this code to BookDriver.main?

Code Interpretation 2

!includesub lesson9.common.puml!VERSION_3

ACTIVITY: Each of the following lines are already in InventoryDriver. for each line below, copy it down, then indicate if it is valid (will compile) or invalid (will not compile) – if it is invalid, then write down why:

Listing 81 Assume this code is in InventoryDriver.main.
 1// we already know the next two lines are valid
 2Book b = new Book("Lord of the Rings");
 3Product p = new Book("The Great Gatsby");
 4
 5// start the activity with the next line
 6InventoryManager im = InventoryManager.getManager();
 7im.addItem(p);
 8im.requestPurchase(p);
 9InventoryManager.nullCheck("main", p);
10im.search(b);
11im.approvePurchase(b);
Solution
  1. Valid

  2. Valid

  3. Valid

  4. Invalid: The nullcheck method is private in the InventoryManager class.

  5. Valid

  6. Valid

Bonus Practice: How would the answers change if we moved this code to BookDriver.main?

Part 4: Discussion

!includesub lesson9.common.puml!VERSION_3

Does anyone have any additional visibility-related questions regarding this UML diagram?

Discussion 1
  • Can the InventoryManager change the serial number of the product in addItem either directly or via setSerial?

  • Can the InventoryManager addItem method call the Product constructor?

  • Can the InventoryManager addItem method call the getSerial method in Product?

Solution
  • Yes, you can call setSerial from addItem since addItem is in the same package.

  • No, because the Product constructor can only be called from a child class using super. This is not related to visibility.

  • Yes

Discussion 2

Look up some protected methods in String using the following command:

javap java.lang.String | grep indexOf

Note

You can add -private to also see private entities.

You should see 2 indexOf methods that are used internally. The users of the String class don’t need to understand how to use those methods - they are meant for internal use.

Remember, visibility is used “to prevent the users of a package or class from depending on unnecessary details of the implementation of that package or class.”