| Objects, Classes, and Interfaces

## Controlling Access to Members of a Class

> 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 start-up 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 are there simply for the personal use of the class. They support the operation of the class but should not be used by objects of another type--you've got secret information to protect. You'd like to be able to protect these personal variables and methods at the language level and disallow access by objects of another type.

> In Java, you can use access specifiers to protect both a class's variables and its methods when you declare them. The Java language supports four distinct access levels for member variables and methods: private, protected, public, and, if left unspecified, package-access.

> Note: The 1.0 release of the Java language supported five access levels: the four listed above plus `private protected`. The `private protected` access level is not supported in versions of Java higher than 1.0; you should no longer be using it in your Java programs.

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

> >     Specifier       class   subclass   package   world
> >     -----------------------------------------------------
> >     private         X
> >     protected       X       X*         X
> >     public          X       X          X         X
> >     package         X                  X

> The first column indicates whether the class itself has access to the member defined by the access specifier. As you can see, a class always has access to its own members. The second column indicates whether subclasses of the class (regardless of which package they are in) have access to the member. The third column indicates whether classes in the same package as the class (regardless of their parentage) have access to the member. The fourth column indicates whether all classes have access to the member.

> Note that the protected/subclass intersection has an '*' -- this particular access case has a special caveat discussed in detail later.

> Let's look at each access level in more detail.

> #### 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 that it's running in. Private members are like secrets you would 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.

> > You can tell when one of your classes is attempting to access a member varible to which it does not have access--the compiler will print an error message similar to the following and refuse 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.

> #### Protected

> > The next access level specifier is protected which allows the class itself, subclasses (with the caveat that we referred to earlier), and all classes in the same package to access the members. Use the protected access level when its 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 wouldn't want any outsiders to know.

> > 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;

> > >     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. `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 objects `protectedMethod()` which is also illegal:

> > >     import Greek.*;

> > >     package Latin;

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

> #### 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 (not a subclass of) to Alpha:

> > >     import Greek.*;

> > >     package Roman;

> > >     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()`.

> #### Package-Access

> > And finally, the last access level is what you get if you don't explicitly set a member's access to one of the other levels. This 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. 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 packageMetho() {
> > >             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
> > >         }
> > >     }

> > Then Beta can legally access `iampackage` and `packageMethod()` as shown.

| Objects, Classes, and Interfaces