Understanding Java'S Protected Modifier

Understanding Java's protected modifier

What's going on here?

You've misunderstood the meaning of protected. You can access the protected members declared in A from within C, but only for instances of C or subclasses of C. See section 6.6.2 of the JLS for details of protected access. In particular:

Let C be the class in which a protected member 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 field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S.

(Emphasis mine.)

So this code would be fine:

C c = new C();
System.out.println(c.publicInt);
System.out.println(c.protectedInt);

What is the difference between public, protected, package-private and private in Java?

The official tutorial may be of some use to you.

















































ClassPackageSubclass
(same pkg)
Subclass
(diff pkg)
World
public+++++
protected++++
no modifier+++
private+

Access modifier Protected

As per https://www.geeksforgeeks.org/access-modifiers-java/ use

//Java program to illustrate 
//protected modifier
package p2;
import p1.*; //importing all classes in package p1

//Class B is subclass of A
class B extends A
{
public static void main(String args[])
{
B obj = new B();
obj.display();
}

}

//Java program to illustrate
//protected modifier
package p1;

//Class A
public class A
{
protected void display()
{
System.out.println("Test");
}
}

i.e you need to instantiate with DiffPackageSubClass class in main because protected has access in different package through subclass.

Protected access modifier in Java

The webpage @MadProgrammer linked gives a decent explanation:

"The protected modifier specifies that the member can only be accessed
within its own package (as with package-private) and, in addition, by
a subclass of its class in another package."

This means the protected member must be accessed directly through either the class it is defined in or a subclass of said class while also being within the appropriate package. It does not necessarily mean you can access the protected member through an instance of said class created within a subclass of said class. The focus is on the packages involved.

Here are your examples:

package first; // Current package

First fst = new First(); // from package first and does not extend anything
fst.pro();

Attempting to access member in question from which package? first

Is the (sub)class, which contains said member, or its parent class, which it inherits the member from, defined within that same package? Yes, First is defined in package first, so the protected member is accessible from First in package first.

package second; // Current package

First fst = new First(); // from package first and does not extend anything
fst.pro();

Attempting to access member in question from which package? second

Is the (sub)class, which contains said member, or its parent class, which it inherits the member from, defined within that same package? No, First is defined in package first, so protected makes the member inaccessible from First in package second.

package second; // Current package

Second sec = new Second(); // from package second and extends First from package first
sec.pro();

Attempting to access member in question from which package? second

Is the (sub)class, which contains said member, or its parent class, which it inherits the member from, defined within that same package? Yes, Second, which is defined in package second, inherits the member from First, so the protected member is accessible from Second in package second.

More examples for clarity:

package first; // Current package

Second sec = new Second(); // from package second and extends First from package first
sec.pro();

Attempting to access member in question from which package? first

Is the (sub)class, which contains said member, or its parent class, which it inherits the member from, defined within that same package? Yes, Second inherits the member from First, which is defined in package first, so the protected member is accessible from Second in package first.

package first; // Current package

Third third = new Third(); // from package third and extends Second from package second,
// which extends First from package first
third.pro();

Attempting to access member in question from which package? first

Is the (sub)class, which contains said member, or its parent class, which it inherits the member from, defined within that same package? Yes, Third inherits the member from Second, which inherits it from First where the member is defined (package first), so the protected member is accessible from Third in package first.

Java protected modifier

I also had the impression what protected meant "accessible from the same package or from a subclass" but the Java Language Specification is of course more precise, and explains that in a subclass S of C, "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."

So you can only access a protected method of the superclass via a reference to the subclass you are calling from, like this:

public class C2 extends C1 {
private C2 c2_other_instance;
public void doItAgain() {
c2_other_instance.doIt();
}
}

If you explain why you want to access one instance of the superclass from a different instance of the subclass then someone might be able to suggest a better design. Otherwise you will have to make the method public or put the classes in the same package.

difference between protected and package-private access modifiers in Java?

The first answer is basically correct - protected members can be accessed by

  • classes from the same package
  • subclasses of the declaring class from other packages

However, there is a little trick:

6.6.2 Details on protected Access

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.

It means that subclass from other package cannot access protected members of arbitrary instances of their superclasses, they can only access them on instances of their own type (where type is a compile-time type of expression, since it's a compile-time check).

For example (assuming that this code is in Cat):

Dog dog = new Dog();
Animal cat = new Cat();

dog.testInstanceMethod(); // Not allowed, because Cat should not be able to access protected members of Dog
cat.testInstanceMethod(); // Not allowed, because compiler doesn't know that runtime type of cat is Cat

((Cat) cat).testInstanceMethod(); // Allowed

It makes sense, because accessing of protected members of Dog by Cat may break invariants of Dog, whereas Cat can access its own protected members safely, because it knows how to ensure its own invariants.

Detailed rules:

6.6.2.1 Access to a protected Member

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.
  • If the access is by a field access expression E.Id, where E is a Primary expression, or by a method invocation expression E.Id(. . .), where E is a Primary expression, then the access is permitted if and only if the type of E is S or a subclass of S.

6.6.2.2 Qualified Access to a protected Constructor

Let C be the class in which a protected constructor is declared and let S be the innermost class in whose declaration the use of the protected constructor occurs. Then:

  • If the access is by a superclass constructor invocation super(. . .) or by a qualified superclass constructor invocation of the form E.super(. . .), where E is a Primary expression, then the access is permitted.
  • If the access is by an anonymous class instance creation expression of the form new C(. . .){...} or by a qualified class instance creation expression of the form E.new C(. . .){...}, where E is a Primary expression, then the access is permitted.
  • Otherwise, if the access is by a simple class instance creation expression of the form new C(. . .) or by a qualified class instance creation expression of the form E.new C(. . .), where E is a Primary expression, then the access is not permitted. A protected constructor can be accessed by a class instance creation expression (that does not declare an anonymous class) only from within the package in which it is defined.

See also:

  • Java Language Specification


Related Topics



Leave a reply



Submit