Class access

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

In
Java, the access specifiers can also be used to determine which classes
within
a library will be available to the users of that library. If you want a class
to be available to a client programmer, you place the
public
keyword somewhere before the opening brace of the class body. This controls
whether the client programmer can even create an object of the class.

To
control the access of a class, the specifier must appear before the keyword
class.
Thus
you can say:

public
class Widget {

That
is, if the name of your library is
mylib
any client programmer can access
Widget
by saying

import
mylib.Widget;

or

import
mylib.*;

However,
there’s an extra pair of constraints:

  1. There
    can be only one
    public
    class per compilation unit (file). The idea is that each compilation unit has a
    single public interface represented by that public class. It can have as many
    supporting “friendly” classes as you want. If you have more than one
    public
    class inside a compilation unit, the compiler will give you an error message.
  2. The
    name of the
    public
    class must exactly match the name of the file containing the compilation unit,
    including capitalization. So for
    Widget,
    the name of the file must be
    Widget.java,
    not
    widget.java
    or
    WIDGET.java.
    Again, you’ll get a compile-time error if they don’t agree.
  3. It
    is possible, though not typical, to have a compilation unit with no public
    class at all. In this case, you can name the file whatever you like.
Note
that a class cannot be
private
(that
would make it accessible to no one but the class), or
protected.
[26]
So you have only two choices for class access: “friendly” or
public.
If you don’t want anyone else to have access to that class, you can make
all the constructors
private,
thereby preventing anyone but you, inside a
static
member of the class, from creating an object of that class.
[27]
Here’s an example:

//: Lunch.java
// Demonstrates class access specifiers.
// Make a class effectively private
// with private constructors:
 
class Soup {
  private Soup() {}
  // (1) Allow creation via static method:
  public static Soup makeSoup() {
    return new Soup();
  }
  // (2) Create a static object and
  // return a reference upon request.
  // (The "Singleton" pattern):
  private static Soup ps1 = new Soup();
  public static Soup access() {
    return ps1;
  }
  public void f() {}
}
 
class Sandwich { // Uses Lunch
  void f() { new Lunch(); }
}
 
// Only one public class allowed per file:
public class Lunch {
  void test() {
    // Can't do this! Private constructor:
    //! Soup priv1 = new Soup();
    Soup priv2 = Soup.makeSoup();
    Sandwich f1 = new Sandwich();
    Soup.access().f();
  }
} ///:~ 

Up
to now, most of the methods have been returning either
void
or a primitive type so the definition:

  public static Soup access() {
    return ps1;
  }

might
look a little confusing at first. The word before the method name (
access)
tells what the method returns. So far this has most often been
void,
which means it returns nothing. But you can also return a handle to an object,
which is what happens here. This method returns a handle to an object of class
Soup.

The
class
Soup

shows how to prevent direct creation of a class by making all the constructors
private.
Remember that if you don’t explicitly create at least one constructor,
the default constructor (a constructor with no arguments) will be created for
you. By writing the default constructor, it won’t be created
automatically. By making it
private,
no one can create an object of that class. But now how does anyone use this
class? The above example shows two options. First, a
static
method is created that creates a new
Soup
and returns a handle to it. This could be useful if you want to do some extra
operations on the
Soup
before returning it, or if you want to keep count of how many
Soup
objects to create (perhaps to restrict their population).


[26]
Actually, a Java 1.1
inner
class

can be private or protected, but that’s a special case. These will be
introduced in Chapter 7.

[27]
You can also do it by inheriting (Chapter 6) from that class.

More by Author

Must Read