Java access specifiers


Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame

Bruce Eckel's Thinking in Java Contents | Prev | Next


  1. Make the member public. Then everybody, everywhere, can access it.
  2. Make the member friendly by leaving off any access specifier, and put the other classes in the same package. Then the other classes can access the member.
  3. As you’ll see in a later chapter where inheritance is introduced, an inherited class can access a protected member as well as a public member (but not private members). It can access friendly members only if the two classes are in the same package. But don’t worry about that now.
  4. Provide “accessor/mutator” methods (also known as “get/set” methods) that read and change the value. This is the most civilized approach in terms of OOP, and it is fundamental to Java Beans, as you’ll see in Chapter 13.

public: interface access

//: Cookie.java
// Creates a library
package c05.dessert;
public class Cookie {
  public Cookie() { 
   System.out.println("Cookie constructor"); 
  void foo() { System.out.println("foo"); }
} ///:~ 

Remember, Cookie.java must reside in a subdirectory called dessert, in a directory under C05 (indicating Chapter 5 of this book) that must be under one of the CLASSPATH directories. Don’t make the mistake of thinking that Java will always look at the current directory as one of the starting points for searching. If you don’t have a ‘ .’ as one of the paths in your CLASSPATH, Java won’t look there.

Now if you create a program that uses Cookie:

//: Dinner.java
// Uses the library
import c05.dessert.*;
public class Dinner {
  public Dinner() {
   System.out.println("Dinner constructor");
  public static void main(String[] args) {
    Cookie x = new Cookie();
    //! x.foo(); // Can't access
} ///:~ 

You can create a Cookie object, since its constructor is public and the class is public. (We’ll look more at the concept of a public class later.) However, the foo( ) member is inaccessible inside Dinner.java since foo( ) is friendly only within package dessert.

The default package

//: Cake.java
// Accesses a class in a separate 
// compilation unit.
class Cake {
  public static void main(String[] args) {
    Pie x = new Pie();
} ///:~ 

In a second file, in the same directory:

//: Pie.java
// The other class
class Pie {
  void f() { System.out.println("Pie.f()"); }
} ///:~ 

You might initially view these as completely foreign files, and yet Cake is able to create a Pie object and call its f( ) method! You’d typically think that Pie and f( ) are friendly and therefore not available to Cake. They are friendly – that part is correct. The reason that they are available in Cake.java is because they are in the same directory and have no explicit package name. Java treats files like this as implicitly part of the “default package” for that directory, and therefore friendly to all the other files in that directory.

private: you can’t touch that!

The private keyword that means no one can access that member except that particular class, inside methods of that class. Other classes in the same package cannot access private members, so it’s as if you’re even insulating the class against yourself. On the other hand, it’s not unlikely that a package might be created by several people collaborating together, so private allows you to freely change that member without concern that it will affect another class in the same package. The default “friendly” package access is often an adequate amount of hiding; remember, a “friendly” member is inaccessible to the user of the package. This is nice, since the default access is the one that you normally use. Thus, you’ll typically think about access for the members that you explicitly want to make public for the client programmer, and as a result, you might not initially think you’ll use the private keyword often since it’s tolerable to get away without it. (This is a distinct contrast with C++.) However, it turns out that the consistent use of private is very important, especially where multithreading is concerned. (As you’ll see in Chapter 14.)

//: IceCream.java
// Demonstrates "private" keyword
class Sundae {
  private Sundae() {}
  static Sundae makeASundae() { 
    return new Sundae(); 
public class IceCream {
  public static void main(String[] args) {
    //! Sundae x = new Sundae();
    Sundae x = Sundae.makeASundae();
} ///:~ 

This shows an example in which private comes in handy: you might want to control how an object is created and prevent someone from directly accessing a particular constructor (or all of them). In the example above, you cannot create a Sundae object via its constructor; instead you must call the makeASundae( ) method to do it for you. [25]

Any method that you’re certain is only a “helper” method for that class can be made private to ensure that you don’t accidentally use it elsewhere in the package and thus prohibit you from changing or removing the method. Making a method private guarantees that you retain this option. (However, just because the handle is private doesn't mean that some other object can't have a public handle to the same object. See Chapter 12 for issues about aliasing.)

protected: “sort of friendly”

//: ChocolateChip.java
// Can't access friendly member
// in another class
import c05.dessert.*;
public class ChocolateChip extends Cookie {
  public ChocolateChip() {
     "ChocolateChip constructor");
  public static void main(String[] args) {
    ChocolateChip x = new ChocolateChip();
    //! x.foo(); // Can't access foo
} ///:~ 

One of the interesting things about inheritance is that if a method foo( ) exists in class Cookie, then it also exists in any class inherited from Cookie. But since foo( ) is “friendly” in a foreign package, it’s unavailable to us in this one. Of course, you could make it public, but then everyone would have access and maybe that’s not what you want. If we change the class Cookie as follows:

public class Cookie {
  public Cookie() { 
    System.out.println("Cookie constructor");
  protected void foo() {

then foo( ) still has “friendly” access within package dessert, but it is also accessible to anyone inheriting from Cookie. However, it is not public.

[25] There’s another effect in this case: Since the default constructor is the only one defined, and it’s private, it will prevent inheritance of this class. (A subject that will be introduced in Chapter 6.)

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date