Tutorial Java SCJP – #17 Access modifiers for methods and attributes

Access modifiers represents ways to give or to restrict access to class variables and methods. One reason is the encapsulation concept that states that instance variables are not accessed directly, but only through access methods (prefixed with get or set). Another reason is to control how the class is used and how and what values are getting into instance variables (ex. if you implement the Person class that has a age instance variable you don’t want to allow other programmers to initialize it directly with any value because they can put a negative one)

Other topics that are part of this Java tutorial are accessible through Java 6 Tutorial – Contents.

The class member access modifiers are:

As seen from the short description, access modifiers represent rules for accessing class members from other classes.

For a single class you will always have access to its methods and variables despite their access modifiers.

What means to see or access a class method or variable

If we analyze a non-static (more on static in the next posts) instance variable or method, you know that using dot (.) operator and a reference you can access its instance variables or call its methods. But because, OOP means to implement more than one class, you can or not to do that from other classes, even they are subclasses on the analyzed one.

So, in Java, to see a class method or variable means to be able to call or access it:

If we consider ClassA defined in package main:

package main;

public class ClassA{
    private int privateAttribute;    	//private
    public int publicAttribute;      	//public

    //class method
    void doSomething(){
	privateAttribute = 10;	//accessible
	publicAttribute = 20;	//accessible
    }
}

and class Main defined in the same package, that has the static method main():

package main;

public class Main {
    public static void main(String[] args) {
        ClassA ref = new ClassA();
        //public attributes are visible
        ref.publicAttribute = 10;

        //private attributes are NOT visible
	//compiler error: privateAttribute has private access in...
        ref.privateAttribute = 20;    //compiler error
    }
}

In the previous example you can’t access the privateAttribute of the ClassA object because it is private and it is accessible only by methods from class ClassA. We can say that privateAttribute  is not visible in class Main. The situation is controlled by the Java compiler, that generates a compiler error with the message atributPrivat has private access in…. The private attribute is accessible only from methods of class ClassA.

In opposition, the public attribute, publicAttribute, is accessible. It is visible in class Main.

The same rules, seen in the previous example for attributes, apply also to methods.

Public access modifier

Public access modifier is the least restrictive because makes the variable or method visible in any other class (subclass or not) and in any package.

If we consider ClassA class defined in package main:

package main;

public class ClassA{
    public int publicAttribute;      //public
}

then, the public attribute is visible, or can be accessed in methods belonging to classes in same package:

package main;   //same package

public class ClassB {
    public static void doSomething()
    {
        ClassA ref = new ClassA();
        ref.publicAttribute = 20;
    }
}

then, the public attribute is visible, or can be accessed in methods belonging to subclasses in same package (more on inheritance in another article):

package main;   //same package

public class SubClassA extends ClassA {
    public void doSomething(){
       
       ClassA ref = new ClassA();

       //accessible using a reference
       ref.publicAttribute = 20;

       //accesible through inheritance
       this.publicAttribute = 30;
    }
}

then, the public attribute is visible, or can be accessed in methods belonging to subclasses in other package:

package other;  //other package

import main.ClassA;

public class OtherSubClassA extends ClassA {
    public void doSomething(){

        ClassA ref = new ClassA();

       //accessible using a reference
       ref.publicAttribute = 20;

       //accesible through inheritance
       this.publicAttribute = 30;
    }
}

then, the public attribute is visible, or can be accessed in methods belonging to classes in other package:

package other;  //other package

import main.ClassA;

public class ClassC {
    public static void doSomething()
    {
        ClassA ref = new ClassA();
        ref.publicAttribute = 20;
    }
}

Private access modifier

Private access modifier is the most restrictive one because blocks the access to the variable or method from code outside the containing class.

So, for private, you can access the attributes and methods ONLY from methods belonging to the same class

package main;

public class ClassA{
    private int privateAttribute;     //private

    public void doSomething(){
        //visible only in the same class
        privateAttribute = 20;
    }
}

Default access modifier

Default (when you don’t write any access modifier) access modifier is between public and private because blocks the access to the variable or method from code outside the same package. It is similar to the default access modifier for classes (see Tutorial Java SCJP – #13 Packages and Class access modifiers) and default attributes or methods are accessible from:

  • same class;
  • other classes in the same package;
  • subclasses in the same package;

For class ClassA:

package main;

public class ClassA{

    int defaultAttribute;             //default

    public void doSomething(){
        //visible in the same class
        defaultAttribute = 20;
    }
}

the defaultAttribute attribute is visible in other classes from the same package:

package main;   //same package

public class ClassB {
    public static void doDomething(){
        ClassA ref = new ClassA();
        ref.defaultAttribute = 30;
    }
}

and from subclasses in the same package

package main;   //same package

public class SubClassA extends ClassA {
    public void doSomething(){
       
       ClassA ref = new ClassA();

       //accessible using a reference
       ref.defaultAttribute = 20;

       //accesible through inheritance
       this.defaultAttribute = 30;
    }
}

Default attributes and methods are NOT visible outside the package (subclasses or classes):

package other;  //other package

import main.ClassA;

public class ClassC {
    public static void doSomething(){
        ClassA ref = new ClassA();
        //NOT visible
        ref.defaultAttribute = 20;  //compiler error
    }
}

Protected access modifier

One advantage of OOP is the inheritance because it allows to develop new classed based on existing ones by extending them and not modifying them.

Because there is a special relation between a base class (the existing one) and the subclass (the new class that extends the base one), you can use an access modifier that grants access to attributes and methods only to subclasses. This access modifier is protected.

package main;

public class ClassA{

    protected int protectedAttribute;    //protected

    public void doSomething(){
        //visible in the same class
        protectedAttribute = 20;
    }
}

Protected attributes are visible in:

– classes in the same package:

package main;   //same package

public class ClassB {
    public static void doSomething(){
        ClassA ref = new ClassA();
        ref.protectedAttribute = 40;
    }
}

– subclasses in the same package (by inheritance and reference)

package main;   //same package

public class SubClassA extends ClassA {
    public void doSomething(){
       
       ClassA ref = new ClassA();

       //accessible using a reference
       ref.defaultAttribute = 20;

       //accesible through inheritance
       this.defaultAttribute = 30;
    }
}

– subclasses in other package (IMPORTANT ! only by inheritance):

package other;  //other package

import main.ClassA;

public class OtherSubClassA extends ClassA {
    public void doSomething(){

        ClassA ref = new ClassA();

       //NOT accessible using a reference
       ref.protectedAttribute = 20; //compiler error

       //accesible through inheritance
       this.protectedAttribute = 30;
    }
}

Protected attributes are NOT visible in classes outside the package:

package other;  //other package

import main.ClassA;

public class ClassC {
    public static void doSomething(){
        ClassA ref = new ClassA();
        //NOT visible
        ref.protectedAttribute = 20;  //compiler error
    }
}

SCJP important facts

For the SCJP exam remember this table that summarize the rules and scenarios:

Visibility

public

protected

private

default

Same class

X

X

X

X

Class in same package

X

X

 

X

Subclass in same package

X

X

 

X

Subclass in other package

X

X

(only by inheritance)

 

 

Class outside the package

X

 

 

 

This topic is important for SCJP exam because if you don’t read carefully the question you can missed a private or default access modifier that will hide the class member or will generate a compiler error:

  • a class will always have access to its methods and variables despite their access modifiers;
  • protected members are visible in subclasses from other packages only by inheritance, meaning that can be accessed through this reference and not by a reference of base class type;
  • before checking class members (attributes or methods) access modifiers, check the class access modifier (default or public – Tutorial Java SCJP – #13 Packages and Class access modifiers);
  • if the class is not visible then neither its members (attributes or methods), even if they are public;

For example, if ClassD is defined as default in main package

package main;

public class Main {
    public static void main(String[] args) {
    }
}

//default class in main package
class ClassD{
    public int publicAttribute;
}

then in ClassC from other package, the class ClassD is NOT visible and hence neither its public attributes:

package other;  //other package

public class ClassC {
    public static void doSomething(){

        //compiler error
        ClassD ref = new ClassD();  //cannot find symbol ClassD
    }
}

Other topics that are part of this Java tutorial are accessible through Java 6 Tutorial – Contents.