Why the protected modifier behave differently here

2019-07-26 10:18发布

问题:

I have the following two class in two different packages. my access modifier for instance method is protected which means any subclass in same or different package has access to it right?. however, in Eclipse I see the following message on my subclass Cat on line 17

The method testInstanceMethod() from the type Animal is not visible 

My code for super and subclass are below.

package inheritance;

public class Animal {

    public static void testClassMethod() {
        System.out.println("The class" + " method in Animal.");
    }
    protected void testInstanceMethod() {
        System.out.println("The instance " + " method in Animal.");
    }
}

package testpackage;

import inheritance.Animal;

public class Cat extends Animal{
        public static void testClassMethod() {
            System.out.println("The class method" + " in Cat.");
        }
        public void testInstanceMethod() {
            System.out.println("The instance method" + " in Cat.");
        }

        public static void main(String[] args) {
            Cat myCat = new Cat();
            Animal myAnimal = myCat;
            myAnimal.testClassMethod();
            myAnimal.testInstanceMethod();
        }
    }

回答1:

The protected access modifier does not grant package access meaning classes within the same package are not granted access to protected fields.

Protected does grants access to classes derived from the base class (inheritance relationship) containing the field and that are in the same package.

So to satisfy protected level access two conditions must be met:

  1. The classes must be in the same package.
  2. There must be an inheritance relationship.

In your example only one of these conditions is satisfied (there is an inheritance relationship between the classes), however they are not in the same package.

If you moved Animal into the same package as Cat the code would compile.

package testpackage;

public class Animal {

    public static void testClassMethod() {
        System.out.println("The class" + " method in Animal.");
    }
    protected void testInstanceMethod() {
        System.out.println("The instance " + " method in Animal.");
    }
}