Java - 帮助我理解从子类访问受保护的成员(再次)

时间:2010-11-23 05:09:45

标签: java subclass access-modifiers protected

好吧,我必须承认我是Java编程的新手,并且非常犹豫在这里发布问题,因为有很多问题与我的问题类似。我已经看过那些问题,但仍然无法理解“受保护”修饰符背后的逻辑是什么。所以我觉得最好在这里发表我自己的问题。

以下是包A

中的课程PackOne
package PackOne;

public class A {

    protected void protectedMethod() {
        System.out.println("A's protectedMethod");
    }

}

以下是包B中的类PackTwo。但是,它是类A的子类。

package PackTwo;

import PackOne.A;

public class B extends A {

    public static void main(String[] args) {

        //Test 1 
        protectedMethod(); //error: non-static method protectedMethod()
                           // cannot be referenced from a static context.

        //Test 2
        A instanceofA = new A();
        instanceofA.protectedMethod();//error: protectedMethod() 
                                      //has protected access in PackOne.A
    }

    public void anotherMethodOfB() {

        //Test 3
        protectedMethod();//Pass 
    }

    //Test 4
    A instanceofA = new A();
    instanceofA.protectedMethod();//error: package instanceofA does not existed.
}

请解释为什么只有测试3对类A中受保护方法的调用通过但其他3个测试(1,2,4)产生错误?

5 个答案:

答案 0 :(得分:2)

这与子类无关。

您无法从静态函数调用非静态方法。现在

public static void main

是静态的,而

protectedMethod()

不是。

其次,你不能从类的“外部”调用受保护的方法。如果您在B类中,则无法调用另一个不是B的类的受保护方法。

最后,在第4点,这段代码不是方法的一部分,所以根本没有任何意义。

答案 1 :(得分:1)

测试1:这与protected / private / public无关 - 您需要A的对象实例来调用此方法。

测试2:您不在A或B的对象实例中,您使用的是静态方法。您需要从A或B中调用受保护的方法 - 在静态方法中不在类中,只有实例计数。

测试3:你在实例中。

测试4:与测试2相同 - 这是一种匿名静态方法。

答案 2 :(得分:1)

由于您无法理解 ,您可以调用实例方法,因此您无法理解protected访问权限。

protectedMethod()是一种可以调用类A实例的方法。

main()中的第一个方法调用无效,因为您没有尝试在A的实例上调用该方法 - main()是一个静态方法,因此它属于B而不是B的实例。

第四个无效,因为您无法将方法作为方法体外的语句调用。

答案 3 :(得分:0)

  • 父类中的protected方法允许子类在内部使用 ,这就是“测试3”通过的原因。
  • 测试1失败,因为main是静态方法,无法访问非静态字段和函数。
  • 测试2失败,因为您尝试通过实例调用protected方法,这是不允许的。与测试4相同。

答案 4 :(得分:0)

要了解您的问题,首先需要了解访问修饰符:

  • 公开:任何类都可以访问此函数/变量。 (您仍然必须先创建实例)
  • 私有:没有其他类可以访问此函数/变量。它只能在课堂内访问。您仍然可以使用该类的公共函数来访问它的私有函数和变量,但不能直接访问。请注意,私有函数和变量是 NOT 继承的(即不是子类的一部分)。
  • 受保护:受保护的函数和变量只能由该类及其任何子类(任何直接/间接从其继承的类)访问。

静态:允许您在不必先创建对象的情况下调用函数。 Math类是一个很好的例子,因为它只包含静态方法和变量(甚至不能实例化)。 (注意:静态不是一个访问修饰符。它还不仅仅是这个,如果你想了解更多,请查找它)

至于你的例子:

  1. 测试1 :您的方法继承自A类,因此可用。但是,由于它不是静态方法,因此无法直接访问:您需要将其设置为静态,或者创建类B的实例,然后通过该实例调用该函数。
  2. 测试2 :这不起作用,因为A& B有不同的包装。只允许在同一个包中访问受保护的方法(即使一个包继承了另一个包)。如果A和B在同一个包中,那就行了。
  3. 测试3 :对象B继承了A的公共方法和受保护方法。它不是A中的方法,而是B中的继承方法。要看到这一点,请更改A的代码以下内容:

    <!-- language: java -->
    
    protected void protectedMethod() {
        System.out.println(getClass().getName() + ("'s Protected method"));
    }
    

    执行此操作将导致B's Protected method

  4. 测试4 :在函数外执行代码不起作用。不要这样做(永远)。

  5. 注意:您可以通过反射访问私有变量和受保护变量,但这是一个更高级的东西。它通常也不是一个很好的想法,因为变量是出于私有/受保护的原因(即防止未经授权的访问/修改)