7
package one;

public class A {
    protected int first;
    protected static int second;
}

package two;

import one.A;

public class B extends A {
    public void someMethod() {
        this.first = 5; //works as expected
        B.second = 6; //works
        A a = new A();
        // a.first = 7; does not compile

        //works just fine, but why?
        a.second = 8; 
        A.second = 9;
    }
}

Why aren't the same restrictions applied to static fields, what's the idea behind it?

Andy Turner
  • 137,514
  • 11
  • 162
  • 243

1 Answers1

6

From JLS 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.

From 6.6.2.1:

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.

this.first = 5; works because B is an implementor of A.

A.second works because this restriction is only defined for members of an object. Same goes for B.second.

As for why it's specified this way, you'd have to ask the people defining the specification - we could only make assumpsions. 6.6.2.1 even has an example that expresses an issue similar to this:

Consider this example, where the points package declares:

package points;
public class Point {
    protected int x, y;
    void warp(threePoint.Point3d a) {
        if (a.z > 0)  // compile-time error: cannot access a.z
            a.delta(this);
    }
}

and the threePoint package declares:

package threePoint;
import points.Point;
public class Point3d extends Point {
    protected int z;
    public void delta(Point p) {
        p.x += this.x;  // compile-time error: cannot access p.x
        p.y += this.y;  // compile-time error: cannot access p.y
    }
    public void delta3d(Point3d q) {
        q.x += this.x;
        q.y += this.y;
        q.z += this.z;
    }
}

A compile-time error occurs in the method delta here: it cannot access the protected members x and y of its parameter p, because while Point3d (the class in which the references to fields x and y occur) is a subclass of Point (the class in which x and y are declared), it is not involved in the implementation of a Point (the type of the parameter p). The method delta3d can access the protected members of its parameter q, because the class Point3d is a subclass of Point and is involved in the implementation of a Point3d.


I recommend checking out Why we should not use protected static in Java.

The semantics of protected were aimed at instance members - protected static is contradictive to the purpose of protected, which could be why it wasn't restricted in the same manner.

Vince
  • 14,470
  • 7
  • 39
  • 84
  • Hi, I couldn't get the answer yet, how protected static variables can access ? In this scenario, a.second = 8; is accessible – nagendra547 Sep 02 '17 at 18:19
  • @nagendra547 The restriction was only set of instance members; class members aren't restricted in this manner. The specification only requires this for instance members. – Vince Sep 02 '17 at 18:22
  • well, you cannot access class members e.g a.second, if B is not extending A. – nagendra547 Sep 02 '17 at 18:25
  • @nagendra547 That's covered by 6.6.2.1: "*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.*" - Since `B` is a subclass of `A`, protected members can be accessed. 6.6.2 enforces the restriction of instance members. Two different contracts. `B` could still access `A.second` without the need to extend only if `B` were in the same package as `A`. – Vince Sep 02 '17 at 18:28
  • I have to say that this 'involved in the implementation of' business is pretty poor wording. 'Member of' would have been a lot better and a lot simpler. – user207421 Sep 02 '17 at 19:02