2017-09-02 88 views
6
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; 
    } 
} 

为什么应用于静态字段不相同的限制,什么是它背后的想法?

回答

6

JLS 6.6.2

受保护的构件或物体可以从它仅由代码中声明封装外部访问的构造,负责该对象的执行。

6.6.2.1

令C是其中一个受保护的成员被声明的类。访问仅在C.

的一个子类小号

this.first = 5;作品,因为BA实现者的身体允许的。

A.second可行,因为这个限制只是为一个对象的成员定义的。 B.second也是如此。

至于为什么它是这样指定的,你必须要求定义规范的人 - 我们只能做出假设。 6.6.2.1甚至有表达类似这样问题的例子:

考虑这个例子,其中点包声明:

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); 
    } 
} 

和三点包装声明:

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; 
    } 
} 

这里的方法增量发生了编译时错误:它不能访问其参数p的受保护成员x和y,因为而Point3d(对x和y的引用发生的类)是子类Point(声明x和y的类)中,它不参与实现Point(参数p的类型)。 delta3d方法可以访问其参数q的受保护成员,因为类Point3d是Point的一个子类,并且参与了Point3d的实现。


我建议检查出Why we should not use protected static in Java

protected的语义是针对实例成员 - protected staticprotected的目的相矛盾,这可能是它为什么不以相同的方式受到限制的原因。

+0

嗨,我还没有得到答案,如何保护静态变量可以访问?在这种情况下,a.second = 8;是可访问的 – nagendra547

+0

@ nagendra547限制只是实例成员的集合;班级成员不受这种限制。规范只需要这个例子成员。 –

+0

好吧,你不能访问类成员,例如a.second,如果B没有扩展A. – nagendra547