Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么另一个包中的子类不能访问受保护的方法?_Java_Package_Subclass_Protected_Modifier - Fatal编程技术网

Java 为什么另一个包中的子类不能访问受保护的方法?

Java 为什么另一个包中的子类不能访问受保护的方法?,java,package,subclass,protected,modifier,Java,Package,Subclass,Protected,Modifier,我有两个不同包中的两个类: package package1; public class Class1 { public void tryMePublic() { } protected void tryMeProtected() { } } package package2; import package1.Class1; public class Class2 extends Class1 { doNow() { Class

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

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
的对象不能使用
c.tryMeProtected()在
Class1
的对象上访问此方法

受保护的方法只能通过包外部的子类继承来访问。因此,第二种方法是
tryMeProtected()工作

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

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

请按照此链接进行更多解释。

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

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

因此,您可以这样做:

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
关键字的特殊性。

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

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

它可以通过两种方式实现

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

包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。或者直接从子类调用方法


eg tryMeProtected()

我相信您误解了
受保护
可见性之间的区别

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
    将可供同一包中的每个类访问(如果子类位于不同的包中,则在子类中不可用)
同班儿童 不同包装的儿童班
首先,你需要了解两件事:

1) 包“Y”中类“X”的受保护的
成员函数可由子类访问,即扩展它的类(即使该子类不在包“Y”中)。所以,

tryMeProtected(); // Showed no error because this was called by class 2 that is the subclass.
2) 如果包“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.

受保护的修饰符为1.Package Private 2.0,可以由其他包的子类看到。 现在,关键区别在于:

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


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

在同一个包外部或在同一个包中(当然都是),不仅在同一个包外部,它们还可以通过单独的实例访问,因为它在java中具有与默认值相同的可见性(除了可以在包外部继承的子类)。是的,我同意,我更喜欢这样一句话:“继承受保护的
方法只有在不同的包中才有意义。”;)@Mik378:是的,正确。我已经修改了帖子中的语句。感谢您指出它。:-)此代码不会产生此错误。方法tryMeProtected()根本不存在。你用你发布的代码测试过吗?如果是,它不能像EJP说的那样工作,你有两个不同的名字:tryMePublic和tryMeProtected@CloudyMarble当然,但是带有protected关键字的继承概念的本质是关于不同的包。否则,默认的包范围就足够了。当然:who可以做得更多,可以做得更少
c.tryMeProtected();  // Showed error because this was called by class 1 reference.
                     //  You can also think of it as class 1 cannot inherit itself.
MyClass1 c = new MyClass1();
    c.tryMeProtected();
tryMyProtected();