Session 6 Lecture Notes for First Course in Java

17-OCT-2005

This lecture covers the reading in Module 6: A Closer Look at Methods and Classes

(syllabus and calendar)

A Closer Look at Methods and Classes

zip of examples


 

Access Control: modifiers

Access Control: Summary

What can be made private? How about an entire class? No. A private class would allow no access and would be useless. There are only two access levels for a class: public or the default, which is accessible within the package.

If you declare a class to be public:

Class Specifier within the package outside the package
public X X
default (undeclared) X  

In Week 8, we will learn more about packages.

For now, let's focus on access levels to class members.

http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html

Controlling Access to Members of a Class: Four Levels

Encapsulation: One of the benefits of classes is that classes can protect their member variables and methods from access by other objects. Why is this important? Well, consider this. You're writing a class that represents a query on a database that contains all kinds of secret information, say employee records or income statements for your startup company.

Certain information and queries contained in the class, the ones supported by the publicly accessible methods and variables in your query object, are OK for the consumption of any other object in the system. Other queries contained in the class support the operation of the class--such as an "internal engine"--but should not be used by objects of another type. You want to protect secret information from, say, programmers in other departments in your company. Or, you want to keep your program stable while third parties make calls into your code using application programming interfaces (API calls) you expose. 

In Java, you can use access specifiers to protect both class variables and methods. You use the access specifier as part of your declaration.
The Java language supports four distinct access levels for member variables and methods: private, protected, public, and, if left unspecified, package.

The following chart shows the access level permitted by each specifier.  

Class Member Specifier class subclass package world
private X      
protected X X
limitation
X  
public X X X X
package X   X  

The class column indicates whether the class itself has access to the member defined by the access specifier.
A class always has access to its own members.
The subclass column indicates whether subclasses of the class (regardless of which package they are in) have access to the member.
The package column indicates whether classes in the same package as the class (regardless of their parentage) have access to the member.
The world column indicates whether all classes have access to the member.

Public

The easiest access specifier is public. Any class, in any package, has access to a class's public members. Declare public members only if such access cannot produce undesirable results if an outsider uses them. There are no personal or family secrets here; this is for stuff you don't mind anybody else knowing.

To declare a public member, use the keyword public. For example,

package Greek;

public class Alpha {
    public int iampublic;
    public void publicMethod() {
        System.out.println("publicMethod");
    }
}

Let's rewrite our Beta class one more time and put it in a different package than Alpha and make sure that it is completely unrelated to (not a subclass of) Alpha:

package Roman;

import Greek.*;

class Beta {
    void accessMethod() {
        Alpha a = new Alpha();
        a.iampublic = 10;       // legal
        a.publicMethod();       // legal
    }
}

As you can see from the above code snippet, Beta can legally inspect and modify the iampublic variable in the Alpha class and can legally invoke publicMethod.

Private

The most restrictive access level is private. A private member is accessible only to the class in which it is defined. Use this access to declare members that should only be used by the class. This includes variables that contain information that if accessed by an outsider could put the object in an inconsistent state, or methods that, if invoked by an outsider, could jeopardize the state of the object or the program in which it's running. Private members are like secrets you never tell anybody.

To declare a private member, use the private keyword in its declaration. The following class contains one private member variable and one private method:

class Alpha {
    private int iamprivate;
    private void privateMethod() {
        System.out.println("privateMethod");
    }
}

Objects of type Alpha can inspect or modify the iamprivate variable and can invoke privateMethod, but objects of other types cannot.
For example, the Beta class defined here:

class Beta {
    void accessMethod() {
        Alpha a = new Alpha();
        a.iamprivate = 10;      // illegal
        a.privateMethod();      // illegal
    }
}

cannot access the iamprivate variable or invoke privateMethod on an object of type Alpha because Beta is not of type Alpha.

When one of your classes is attempting to access a member variable to which it does not have access, the compiler prints an error message similar to the following and refuses to compile your program:

Beta.java:9: Variable iamprivate in class Alpha not 
accessible from class Beta.
        a.iamprivate = 10;     // illegal
         ^
1 error

Also, if your program is attempting to access a method to which it does not have access, you will see a compiler error like this:

Beta.java:12: No method matching privateMethod()
found in class Alpha.
        a.privateMethod();         // illegal
1 error

New Java programmers might ask if one Alpha object can access the private members of another Alpha object. This is illustrated by the following example. Suppose the Alpha class contained an instance method that compared the current Alpha object (this) to another object based on their iamprivate variables:

class Alpha {
    private int iamprivate;
    boolean isEqualTo(Alpha anotherAlpha) {
        if (this.iamprivate == anotherAlpha.iamprivate)
            return true;
        else
            return false;
    }
}

This is perfectly legal. Objects of the same type have access to one another's private members. This is because access restrictions apply at the class or type level (all instances of a class) rather than at the object level (this particular instance of a class).

Note: this is a Java language keyword that refers to the current object. For more information about how to use this see The Method Body.


Package

The package access level is what you get if you don't explicitly set a member's access to one of the other levels.
The package access level allows classes in the same package as your class to access the members.
This level of access assumes that classes in the same package are trusted friends.
The existence of inheritance outside the package does not grant access: subclasses that are not in the package do not have access.
This level of trust is like that which you extend to your closest friends but wouldn't trust even to your family.

For example, this version of the Alpha class declares a single package-access member variable and a single package-access method. Alpha lives in the Greek package:

package Greek;

class Alpha {
    int iampackage;
    void packageMethod() {
        System.out.println("packageMethod");
    }
}

The Alpha class has access both to iampackage and packageMethod. In addition, all the classes declared within the same package as Alpha also have access to iampackage and packageMethod. Suppose that both Alpha and Beta were declared as part of the Greek package:

package Greek;

class Beta {
    void accessMethod() {
        Alpha a = new Alpha();
        a.iampackage = 10;     // legal
        a.packageMethod();     // legal
    }
}

Beta can legally access iampackage and packageMethod as shown.


Protected [Note: Limitation on Subclasses]

Protected access means the members of all the following have access:

Use the protected access level when it's appropriate for a class's subclasses to have access to the member, but not unrelated classes.
Protected members are like family secrets--you don't mind if the whole family knows, and even a few trusted friends, but you hide your family secrets from outsiders in the world at large.

To declare a protected member, use the keyword protected. First, let's look at how the protected specifier affects access for classes in the same package. Consider this version of the Alpha class, which is now declared to be within a package named Greek, and which has one protected member variable and one protected method declared in it:

package Greek;

public class Alpha {
    protected int iamprotected;
    protected void protectedMethod() {
        System.out.println("protectedMethod");
    }
}

Now, suppose that the class Gamma was also declared to be a member of the Greek package (and is not a subclass of Alpha).
The Gamma class can legally access an Alpha object's iamprotected member variable and can legally invoke its protectedMethod:

package Greek;

class Gamma {
    void accessMethod() {
        Alpha a = new Alpha();
        a.iamprotected = 10;    // legal
        a.protectedMethod();    // legal
    }
}

That's pretty straightforward. Now, let's investigate how the protected specifier affects access for subclasses of Alpha.

Let's introduce a new class, Delta, that derives from Alpha but lives in a different package--Latin. The Delta class can access both iamprotected and protectedMethod, but only on objects of type Delta or its subclasses. The Delta class cannot access iamprotected or protectedMethod on objects of type Alpha.
The Delta class has access to what Delta inherits as a subclass of Alpha, but Alpha itself is protected from encroachment by its subclass in a foreign package.
accessMethod
in the following code sample attempts to access the iamprotected member variable on an object of type Alpha, which is illegal, and on an object of type Delta, which is legal.
Similarly, accessMethod attempts to invoke an Alpha object's protectedMethod, which is also illegal:

package Latin;

import Greek.*;

class Delta extends Alpha {
    void accessMethod(Alpha a, Delta d) {
        a.iamprotected = 10;    // illegal
        d.iamprotected = 10;    // legal
        a.protectedMethod();    // illegal
        d.protectedMethod();    // legal
    }
}

If a class is both a subclass of and in the same package as the class with the protected member, then the class has access to the protected member.


How does the ok method (lines 33-37) work?

 


Which lines instantiate objects?
In line 33, is ob2 a formal parameter?
What makes it possible for ob.a to sometimes have a different value than a?


Primitive types can be referenced by variables that have their own copy. The runtime arguments a and b remain unaffected by value changes within the noChange method.

Object types can be reference by variables that point to the object in memory. What enables the change method to change values?


Does the getErrorMsg method return a primitive?

This version uses a different mechanism to print out a message. What are declared in lines 3 and 4?


Methods can be overloaded if each one has a  parameter list with a unique signature:


The unique constructor rule applies, as well, to constructors.


Just as a method can take an object argument at runtime, so can a constructor.


Does this application have an overloaded constructor?
The queue is a first-in-first-out (FIFO) data structure. Which access specifiers protect its data integrity?


Recursion means that a method calls itself. Which line makes the recursive call?


If a class member is static, it stands its own ground, if you will, available before and independently of object creation.
Insofar as a static member is globally shared among all objects of a given type, that static member is unchanging.
However, the value of a static member can change--but whatever its current value, it is the unchanging between the objects of the type.
To reference a static member, you can do either of the following:

Are both of these options valid for class members that are not static?


Here's a static method. What would we have to do if System.out.println() were not static?


To make a set of items available independent of object instantiate, put them in a static block. Which lines define the scope of the static block?


How does the Quicksort algorithm work? Why is it quicker than the Bubble sort?
Why is qs private?


A new feature of J2SE5 is the varargs method, which is flexible in the number of arguments passed to a method.
What is the data type of v?
How does this example compare to our discussion of an overloaded method requiring a unique signature?
In the signature for the vaTest method, can the variable-length argument precede the String argument?