受保护的成员访问java中不同的包 - 一个好奇心

时间:2011-04-06 07:00:06

标签: java protected

package packageOne;
public class Base
{
    protected void display(){
        System.out.println("in Base");
    }
}


package packageTwo;
public class Derived extends packageOne.Base {
    public void show(){
        new Base().display(); //this is not working throws compilation error that display() from the type Base is not visible
        new Derived().display(); //is working
        display(); //is working
    }
}

这两个包有两个不同的文件。但为什么会这样呢?

9 个答案:

答案 0 :(得分:14)

protected允许从同一包中的其他类访问子类。这就是为什么任何Derived类实例都可以访问Base中的受保护方法。

另一行创建Base实例(不是Derived实例!!)。并且只允许从同一个包的对象访问该实例的受保护方法。


display();

- > 允许,因为调用者,Derived的实例可以访问受保护的成员及其子类的字段,即使它们位于不同的包中

new Derived().display();

- > 允许,因为您在Derived的实例上调用该方法,并且该实例可以访问其子类的受保护方法

new Base().display();

- > 不允许因为调用者(this实例)类未在Base类的同一个包中定义,因此this无法访问受保护的类方法。并且 - 正如我们所看到的那样 - 当前从该包中对类进行子类化并不重要。 后门已关闭;)

答案 1 :(得分:3)

受保护的访问权限有一些特殊规则,详见Java Language Specification

  

对象的受保护成员或构造函数可以从包外部访问,只能通过负责实现该对象的代码来声明它。

答案 2 :(得分:3)

http://java.sun.com/docs/books/jls/third_edition/html/names.html#6.6

class C
    protected member;

// in a different package

class S extends C 

    obj.member; // only allowed if type of obj is S or subclass of S

动机可能如下。如果objS,则类S具有足够的内部知识,它有权操纵其成员,并且可以安全地执行此操作。

如果obj不是S,则可能是S2的另一个子类CS根本不知道。撰写S2时,S可能甚至没有出生。 S操纵S2受保护的内部是非常危险的。如果允许这样做,从S2的角度来看,它不知道谁将篡改其受保护的内部以及如何,这使得S2很难对自己的状态进行推理。< / p>

如果objDD extends SS访问obj.member会有危险吗?并不是的。 S使用member的方式是S及其所有子类的共享知识,包括DS因为超类有权定义行为,D因为子类有义务接受和遵守。

为了便于理解,该规则应该简化为要求obj的(静态)类型正好S。毕竟,子类D出现在S中是非常不寻常和不合适的。即使它发生了,obj的静态类型是D,我们的简化规则也可以通过向上转换轻松处理它:((S)obj).member

答案 3 :(得分:1)

new Base().display();

它创建一个Base对象,然后尝试调用它上面的display()。 显然它不起作用,因为Base上的display()受到保护。

答案 4 :(得分:1)

首先想到的是,您可以在任何商品中使用protected Object,但只有不同的包非子类无法从其他类访问受保护的成员。这意味着你无法直接使用它。首先你得到那个obj,然后使用。

    package Demos;

    public class AB
    {
        public    int a = 14;
        protected int b = 13;   
    }

我们还有另一个类

package Example;

import Demos.AB;

public class Ex1 extends AB
{
    public static void main(String[] args)
    {
        AB obj = new AB();          // obj of AB                OR
                                    // AB obj = new Ex1(); object of Ex1 but referance of AB
                                    // cant use protacted member

        System.out.println(obj.a);
        System.out.println(obj.b);  //You can't use 


        Ex1 obj1 = new Ex1();       // you have to make obj of sub-class referance of Ex1
        System.out.println(obj1.a);
        System.out.println(obj1.b);  // Now You can use
    }
}

在这个问题上你必须扩展受保护成员的类然后使用你不能直接使用。

答案 5 :(得分:0)

这是预期的行为。 protected表示继承的类和相同的包类可以看到该方法。所以,这就是你所看到的。

答案 6 :(得分:0)

这可能是您问题的直接答案,但我认为没有理由为您致电新Base().display();。也许你在super.display();中的意思。

在这种情况下,您实际上是在使用继承的方法,但仅仅因为您继承了一个类,并不意味着您可以访问 受保护的方法(根据定义,只对超类可见)。

区别在于您尝试从您继承的类的实例访问受保护方法的一种情况(您的示例)。在我的示例中,您可以通过继承访问受保护的方法。

总结:您可以通过继承上下文访问该方法。

为什么?

它为程序员提供了灵活性,可以决定哪些功能只能由直接后代使用或扩展。

答案 7 :(得分:0)

对象的受保护成员或构造函数可以从包外部访问,只能通过负责实现该对象的代码来声明它。

答案 8 :(得分:-1)

display不是Base中的静态方法。因此,您必须首先创建一个Base实例,然后调用display。

Base base = new Base();
base.display();