Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: protected access across packages

I would like to understand what's happening in the example below (where a protected member is being accessed from outside the package through a subclass).

I know for classes outside the package, the subclass can see the protected member only through inheritance.

There are two packages: package1 and package2.

  1. package1: ProtectedClass.java

    package org.test.package1;
    
    public class ProtectedClass {
    
        protected void foo () {
            System.out.println("foo");
        }
    }
    
  2. package2: ExtendsprotectedClass.java

    package org.test.package2;
    
    import org.test.package1.ProtectedClass;
    
    public class ExtendsprotectedClass  extends ProtectedClass {
    
        public void boo() {
            foo(); // This works, 
                   // since protected method is visible through inheritance
        }
    
        public static void main(String[] args) {
            ExtendsprotectedClass epc = new ExtendsprotectedClass();
            epc.foo(); // Why is this working? 
                       // Since it is accessed through a reference,
                       // foo() should not be visible, right?
        }
    }
    
  3. package2: UsesExtendedClass.java

    package org.test.package2;
    
    public class UsesExtendedClass {
    
        public static void main(String[] args) {
            ExtendsprotectedClass epc = new ExtendsprotectedClass();
            epc.foo(); // CompilationError: 
                       // The method foo() from the type ProtectedClass
                       // is not visible
        }
    }
    

It is understood that the boo() method in ExtendsprotectedClass can access foo(), since protected members can be accessed through inheritance only.

My question is, why is the foo() method working fine when accessed through a reference in the main() method of ExtendsprotectedClass but will not work when accessed through the epc reference in UsesExtendedClass?

like image 594
JWhiz Avatar asked Aug 22 '10 07:08

JWhiz


People also ask

How do I access protected variables in another package?

Protected Access Modifier - Protected Variables, methods, and constructors, which are declared protected in a superclass can be accessed only by the subclasses in other package or any class within the package of the protected members' class. The protected access modifier cannot be applied to class and interfaces.

Can we access protected member outside the package in Java?

The protected access modifier is accessible within the package. However, it can also accessible outside the package but through inheritance only. We can't assign protected to outer class and interface.

Is protected accessible within package?

The protected access modifier is accessible within package and outside the package but through inheritance only. The protected access modifier can be applied on the data member, method and constructor. It can't be applied on the class. It provides more accessibility than the default modifer.

Can protected members be accessed outside the package?

A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.


1 Answers

Code within the ExtendsprotectedClass class is allowed to access protected members of ProtectedClass via a reference of type ExtendsprotectedClass. From the JLS section 6.6.2:

A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.

and

Let C be the class in which a protected member m is declared. Access is permitted only within the body of a subclass S of C. In addition, if Id denotes an instance field or instance method, then:

  • If the access is by a qualified name Q.Id, where Q is an ExpressionName, then the access is permitted if and only if the type of the expression Q is S or a subclass of S. [...]

UsesExtendedClass isn't reponsible for the implementation of ExtendsprotectedClass, hence the final call fails.

EDIT: The reasoning behind this is that protected access is designed to help subclasses implement the functionality they need, giving more access to the internals of the superclass than would normally be available. If that were available to all code, it would be pretty close to making the method public. Basically, the subclasses are trusted not to break encapsulation; they're given more capabilities within objects of their own type. The public API shouldn't expose those details, but the protected API can just for the purposes of giving subclasses more opportunities.

like image 180
Jon Skeet Avatar answered Oct 19 '22 23:10

Jon Skeet