19

我在两个不同的包中有两个类:

package package1;

public class Class1 {
    public void tryMePublic() {
    }

    protected void tryMeProtected() {
    }
}


package package2;

import package1.Class1;

public class Class2 extends Class1 {
    doNow() {
        Class1 c = new Class1();
        c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1
        tryMeProtected();  // No error
    }    
}

我可以理解为什么调用没有错误,tryMeProtected()因为Class2看到这个方法继承自Class1.

但是为什么对象Class2不能访问Class1using 对象上的这个方法c.tryMeProtected(); 呢?

4

7 回答 7

17

受保护的方法只能通过包外的子类中的继承来访问。因此,第二种方法tryMeProtected();有效。

下面的代码不会编译,因为我们没有调用受保护方法的继承版本。

 Class1 c = new Class1();
 c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1

请按照此stackoverflow链接获取更多说明。

于 2013-11-13T08:56:03.503 回答
13

package我相信您误解了可见性和protected可见性之间的区别。

package package1;

public class MyClass1 {
    public void tryMePublic() { System.out.println("I'm public"); }
    protected void tryMeProtected() { System.out.println("I'm protected"); }
    void tryMePackage() { System.out.println("I'm package"); }
}
  • tryMePublic无论您身在何处都可以访问。
  • tryMeProtected每个子类和同一个包中的每个类都可以访问。
  • tryMePackage同一包中的每个类都可以访问(如果它们在不同的包中,则在子类中不可用)

同包儿童班

package package1;

public class Class2 extends MyClass1 {
    public void doNow() {
        tryMePublic(); // OK
        tryMeProtected(); // OK
        tryMePackage(); // OK
    }    
}

不同包装的儿童班

package package2;

import package1.MyClass1;

public class Class3 extends MyClass1 {
    public void doNow() {
        MyClass1 c = new MyClass1();
        c.tryMeProtected() // ERROR, because only public methods are allowed to be called on class instance, whereever you are
        tryMePublic(); // OK
        tryMeProtected(); // OK
        tryMePackage(); // ERROR
    }    
}
于 2016-04-28T10:27:46.087 回答
3

您使用两个不同的包,并且您不通过直接继承访问您的父属性,而是通过在子类中声明的中间父实例(类似于组合)。=> 那不是工作方式protected

只有直接继承才允许访问受保护的父级属性。

因此,您可以这样做:

public class Class2 extends Class1 {
    doNow() {
        tryMeProtected();  // No error since direct inheritance 
    }    
}

但从来没有这个:

public class Class2 extends Class1 {
    doNow() {
        Class1 c = new Class1();
        c.tryMeProtected(); // this is not a direct inheritance! since `c`, although a parent one is an intermediate instance created in the child instance. => bad
    }    
}

确实,这是一个protected经常被误解的关键字的特殊性。

于 2013-11-13T08:57:04.597 回答
2

首先,你需要明白两件事:

1)protected包'Y'中的类'X'的成员函数可以被子类访问,即扩展它的类(即使子类在包中,而不是'Y')。这就是为什么,

tryMeProtected(); // Showed no error because this was called by class 2 that is the subclass.

2) 如果protected包'Y'中的类'X'的成员函数在其他包中,则它本身不能被访问。

[ 一个简单的类比:鸟的蛋放在巢 1 中,它飞到了巢 2。从巢 2 中,它不能访问保存在巢 1 中的蛋。] 同样,一个类也不能访问它的成员函数(除非public 声明。)如果它在另一个包中。

这就是为什么 :

c.tryMeProtected();  // Showed error because this was called by class 1 reference.
                     //  You can also think of it as class 1 cannot inherit itself.
于 2018-08-06T06:19:41.747 回答
1

根据 Java Protected Access 修饰符定义,在超类中声明为 protected 的方法只能由其他包中的子类或受保护成员类的包中的任何类访问。

您不能通过创建类的对象来访问受保护的方法。因此,要访问 Protected 方法,您必须扩展超类。(这说明您的第二次调用是正确的)

于 2013-11-13T09:08:25.353 回答
0

可以通过两种方式实现

1.通过创建子类的对象,然后访问父类的受保护方法。

套餐一

public class Class1 {
    protected void m1() {
        System.out.println("m1 called");
    }
}

包2

public class Class2 extends Class1 {

    public static void main(String[] args) {
        Class2 class2 = new Class2();
        class2.m1();
    }
}

2. 或者直接调用 Child 类的方法

eg tryMeProtected();

于 2014-02-04T11:09:40.650 回答
0

protected 修饰符是 1.Package Private 2.可以被其他包的子类看到。现在的主要区别是:

MyClass1 c = new MyClass1();
    c.tryMeProtected();

tryMyProtected(); 

是使用 MyClass1 引用而不是继承。MyClass1 位于不同的包中,并且此代码不是从 MyClass1 继承的。

于 2020-03-29T21:49:49.740 回答