OCA Java SE 8 Method - Java Method Access Modifiers








Question

There are four access modifiers: public, private, protected, and default access.

  • private: Only accessible within the same class
  • default (package private) access: private and other classes in the same package
  • protected: default access and child classes
  • public: protected and classes in the other packages




Private Access

Only code in the same class can call private methods or access private fields.

This is perfectly legal code because everything is one class:

package com.java2s; 

public class Employee { 
   private String empName = "sayName"; 
   private void sayName() { 
      System.out.println(empName);     // private access is ok 
   } 
   private void makeNoise() { 
      sayName();                    // private access is ok 
   } 
} 

Employee makes a call to private method sayName() and uses private instance variable empName.

Now we add another class:

package com.java2s; 
public class Main { 
  public void makeNoise() { 
     Employee emp = new Employee(); 
     emp.sayName();                       // DOES NOT COMPILE 
     System.out.println(emp.empName);     // DOES NOT COMPILE 
  } 
} 

Main is trying to access private method in another class. It tries to access a private instance variable in another class.

Accessing private members of other classes is not allowed.





Default (Package Private) Access

Default (Package Private) Access allows classes in the same package to access the members.

When there is no access modifier, Java uses the default, which is package private access.

This means that the member is "private" to classes in the same package.

Only classes in the package may access it.

package com.java2s; 

public class Employee { 
  String empName = "sayName"; 
  void sayName() { 
     System.out.println(empName);     // default access is ok 
  } 
  private void makeNoise() { 
     sayName();                    // default access is ok 
  } 
} 

Employee can call sayName() and refer to empName.

After all, members in the same class are certainly in the same package. Employee lets other classes in the same package access members (due to being package private) whereas Employee doesn't (due to being private).

package com.java2s; 

public class Main { 
  public void makeNoise() { 
    Employee emp = new Employee(); 
    emp.sayName();                         // default access 
    System.out.println(emp.empName);          // default access 
  } 
} 

Main succeeds in learning to sayName() and make empName by copying its mother.

All the classes we've covered so far are in the same package com.java2s. This allows default (package private) access to work.

The Main class from com.java2s.beans

package com.java2s.beans; 

import com.java2s.Employee;          // import another package 

public class Main { 
  public void makeNoise() { 
     Employee emp = new Employee(); 
     emp.sayName();                       // DOES NOT COMPILE 
     System.out.println(emp.empName);     // DOES NOT COMPILE      
  } 
} 

Employee restricts access to the com.java2s package.

Remember that when there is no access modifier, only classes in the same package can access it.

Protected Access

Protected access allows everything that default (package private) access allows and more.

The protected access modifier adds the ability to access members of a parent class. First, we create a Person class and give protected access to its members:

package com.java2s.lib; 

public class Person { 
  protected String text = "floating";          // protected access 
  protected void doStuff() {               // protected access 
    System.out.println(text); 
  } 
} 

Next we create a subclass:

package com.java2s.lib.ext; 
import com.java2s.lib.Person;               // in a different package 
public class Employee extends Person {     // extends means create subclass 
  public void work() { 
     doStuff();               // calling protected member 
     System.out.println(text);     // calling protected member 
  } 
} 

This is a very simple subclass.

It extends the Person class.

Extending class creates a subclass that has access to any protected or public members of the parent class.

Since Employee is a subclass of Person, it can access these members even though it is in a different package.

Remember that protected also gives us access to everything that default access does.

This means that a class in the same package as Person can access its protected members.

package com.java2s.lib;                    // same package as Person 

public class PersonWatcher { 
  public void watchPerson() { 
    Person per = new Person(); 
    per.doStuff();               // calling protected member 
    System.out.println(per.text);     // calling protected member 
  } 
} 

Since Person and PersonWatcher are in the same package, PersonWatcher can access members of the per variable.

The definition of protected allows access to subclasses and classes in the same package.

This example uses the same package part of that definition.

Now let's try the same thing from a different package:

package com.java2s.util; 

import com.java2s.lib.Person;               // different package than Person 
public class PersonWatcherFromAfar { 
  public void watchPerson() { 
     Person per = new Person(); 
     per.doStuff();               // DOES NOT COMPILE 
     System.out.println(per.text);     // DOES NOT COMPILE 
  } 
} 

PersonWatcherFromAfar is not in the same package as Person and it doesn't inherit from Person.

This means that it is not allowed to access protected members of Person.

Subclasses and classes in the same package are the only ones allowed to access protected members.

There is one gotcha for protected access. Consider this class:

1:  package com.java2s.beans; 
2:  import com.java2s.lib.Person;     // in different package than Person 
3:  public class Student extends Person {     // but subclass of per 
4:    public void work() { 
5:      doStuff();               // package access to superclass 
6:      System.out.println(text);     // package access to superclass 
7:    } 
8:    public void studentHelper() { 
9:      Student other = new Student(); 
10:     other.doStuff();          // package access to superclass 
11:     System.out.println(other.text);// package access to superclass 
12:   } 
13:   public void personHelper() { 
14:     Person other = new Person(); 
15:     other.doStuff();               // DOES NOT COMPILE 
16:     System.out.println(other.text);      // DOES NOT COMPILE 
17:   }  
18: } 

Student is not in the same package as Person, but does extend it-which implies it has access to the protected members of Person since it is a subclass.

Lines 10 and 11 also successfully use protected members of Person. This is allowed because these lines refer to a Student object.

Student inherits from Person so this is okay. It is sort of a two-phase check. The Student class is allowed to use protected members of Person and we are referring to a Student object.

Granted, it is a Student object created on line 9 rather than an inherited one, but it is still a Student object.

Lines 15 and 16 do not compile. Wait a minute.

They are almost exactly the same as lines 10 and 11!

There's one key difference. This time a Person reference is used. It is created on line 14. Person is in a different package, and this code isn't inheriting from Person, so it doesn't get to use protected members.

We just got through saying repeatedly that Student inherits from Person. And it does. However, the variable reference isn't a Student. The code just happens to be in the Student class.

The protected rules apply under two scenarios:

A member is used without referring to a variable. This is the case on lines 5 and 6. In this case, we are taking advantage of inheritance and protected access is allowed.

A member is used through a variable. This is the case on lines 10, 11, 15, and 16.

Public Access

public means anyone can access the member from anywhere.

package com.java2s; 

public class Employee { 
  public String name = "helpful";     // public access 
  public void work() {               // public access 
     System.out.println("work"); 
  } 
} 

Employee allows access to any class that wants it. Now we can try it out:

package com.java2s.lib.ext; 

import com.java2s.Employee; 
public class Main { 
  public void work() { 
     Employee teacher = new Employee(); 
     teacher.work();                                   // allowed 
     System.out.println("Thanks" + teacher.name);     // allowed 
  }
} 

Main is able to refer to work() and name on Employee because they are public.