public vs. private
Stop! - Can't touch this
Java attempts to achieve data hiding via access modifiers. That is, it lets the programmar specify the access level of a name. The old view of object-oriented programming was concerned with hiding the data internal to an object and only exposing that which users of the class would need. This design choice gives programmers somewhat of a contract, its not infallable, that what they specify as hidden will be hidden to users of their code. By hidden, we mean that client code cannot access it. Hence access modifiers, they modify the access of a name.
Java has 4 access modifiers, public, private, protected, and the
implicit package-private. Classes, methods, and some variables may
be prefixed with an access modifier.
What does each access modifier mean?
Before we look at which things allow access modifiers, we need to know what each of the four modifiers mean. In order of accesibility, from least to most:
private
private is the most restrictive, only within that class can you
access that name, regardless of subclassing. Consider the access of
i, declared in class A.
package A;
public class A {
private int i;
void timesTwo() {
return i * 2; // OK
}
}package A; // same package
public class B extends A { // B is a subclass of A
public void foo() {
A a = new A();
System.out.println(a.i); // <- can't see i, won't compile
}
}package-private
package-private is more open than private. It is the default
access modifier, meaning that to declare a name to be
package-private, simply omit an access modifier. A
package-private name can be thought of as public to everyone
within the same package, private to anyone outside the
package. Consider the access of class A.
package A;
class A {
}package A; // same package
class B {
private A a; // OK
}package C; // different package
class C {
private A a; // <- can't see A, won't compile
}protected
protected is slightly more open than package-private. A
protected name is accessible to those in the same package or any
subclasses (even if that subclass is in a different package). Consider
the access of i, defined in class A.
package A;
public class A {
protected int i;
}package A; // same package
public class Another {
public void foo() {
A a = new A();
System.out.println(a.i); // OK
}
}package B; // different package
class B extends A { // B is a subclass of A
void foo() {
A a = new A();
System.out.println(a.i); // OK
}
}public
public means anyone can access that symbol, regardless of their
relationship with or the package of the declaring class. Consider the
access of class A.
package A;
public class A {
}package B;
public class B {
private A a; // OK
}B can declare an instance variable of type A since the class A
is publicly visible. The access modifier of class B or variable a
has no implications on whether B can "see" A.
What names can take access modifiers?
A class can take either the public or package-private access
modifier to dictate if that class is visible to other classes. Each
java file can contain only one public top-level class, it can contain
any number of package-private top-level classes as well as nested
classes. For example:
package example;
// Any other class can use Class, it's public
public class Class {
class InnerClass {
}
}
// only classes within the example package can use me
class HelperClass {
}All methods can take an access modifier to dictate if that method can be called from within other classes.
public class Class {
// everyone can see the constructor
public Class() { }
// this function is only visible within this class
private int helper_function() { return 0; }
}A variable may take an access modifier depending on where it is declared. If a variable is declared at class scope, it can take an access modifier. If a variable is declared within a function, it cannot take an access modifier since its visibility is already limited to within that function.
public class Class {
public final double PI = 3.14; // anyone can access this
private int myID; // only within this class is myID accessible
public void foo() {
int counter;
public double num; // <- this won't compile
}
}