One of the most important aspects of object-oriented design is data hiding, or encapsulation. By treating an object in some respects as a "black box" and ignoring the details of its implementation, we can write stronger, simpler code with components that can be easily reused.
By default, the variables and methods of a class are accessible to members of the class itself and other classes in the same package. To borrow from C++ terminology, classes in the same package are friendly. We'll call this the default level of visibility. As you'll see as we go on, the default visibility lies in the middle of the range of restrictiveness that can be specified.
The modifiers public and
private, on the other hand, define the extremes. As
we mentioned earlier, methods and variables declared as
private are accessible only within their class. At
the other end of the spectrum, members declared as
public are always accessible, from any class in any
package. Of course, the class that contains the methods must also be
public, as we just discussed. The
public members of a class should define its most
general functionality--what the black box is supposed to do.
Figure 6.7 illustrates the four simplest levels
of visibility.

Figure 6.7 continues with the example from
the previous section. Public members in TextArea
are accessible from anywhere. Private members are not visible from
outside the class. The default visibility allows access by other
classes in the package.
The protected modifier allows special access
permissions for subclasses. Contrary to how it might sound,
protected is slightly less restrictive than the
default level of accessibility. In addition to the default access
afforded classes in the same package, protected
members are visible to subclasses of the class, even if they are
defined in a different package. If you are a C++ programmer and so
used to more restrictive meanings, this may rub you the
wrong way.
[3]
[3] Early on, the Java language allowed for certain combinations of modifiers, one of which was
private protected. The meaning of private protected was to limit visibility strictly to subclasses (and remove package access). This was later deemed confusing and overly complex and is no longer supported.
Table 6.1 summarizes the levels of visibility available in Java; it runs generally from most restrictive to least. Methods and variables are always visible within a class, so the table doesn't address those.
| Modifier | Visibility |
|---|---|
private | None |
| none (default) | Classes in the package |
protected | Classes in package and subclasses inside or outside the package |
public | All classes |
Subclasses add two important (but unrelated) complications to the
topic of visibility. First, when you override methods in a subclass,
the overriding method must be at least as visible as the overridden
method. While it is possible to
take a private method and override it with a
public method in a subclass, the reverse is not
possible; you can't override a public
method with a private method. This
restriction makes sense if you realize that subtypes
have to be usable as instances of their supertype (e.g., a
Mammal is a subclass of
Animal and therefore must be usable as an
Animal). If
we could override a method with a less visible method, we would have a
problem: our Mammal might not be able to
do all the things an Animal can.
However, we can reduce the visibility of a variable because
it simply results in a shadowed variable. As with all shadowed
variables, the two variables are distinct and can have separate
visibilities in different classes.
Second, the protected variables
of a class are visible to its subclasses, but only in
objects of the subclass's type or its subtypes. In other words,
a subclass can see a protected variable from its
superclass as an inherited variable, but it can't access the variable in
a separate instance of the superclass itself.
This can be confusing because we often forget that visibility modifiers
don't restrict access between instances of the same class in the same way
that they restrict access between instances of different classes. Two
instances of the same type
of object can normally access all of each other's members,
including private ones. Said another way: two instances of
Cat can access
all of each other's variables and methods (including private ones), but a
Cat can't access a protected member in an
instance of Animal unless the compiler
can prove that the Animal is a
Cat.
Interfaces behave like classes within packages. An interface can be declared
public to make it visible outside of its package.
Under the default visibility, an interface is visible only inside of its
package. There can be only one public interface
declared in a compilation unit.