> 文档中心 > java中的保护(protected)修饰符的理解

java中的保护(protected)修饰符的理解

java中的保护(protected)修饰符的理解

protected修饰符给出的大部分定义解释都为 protected修饰的成员(下文中的成员统一指代属性和方法),允许同包下的类和不同包的子类访问。
注意这里的异包下的子类访问是指通过继承访问父类中的protected属性或方法(就是子类实例进行访问),而不是直接通过创建父类实例然后访问protected属性或方法。

也就是protected修饰的成员,只可以被同包的类访问。这一点很关键
这句话的意思就是:子类通过继承,可以在自己的类中访问自己的protected成员,但是不能访问异包类(同包的可以访问)的protected成员(即使是自己的超类)。这是为了避免通过派生子类来访问父类受保护的成员。

1.People类(所有测试类可以继承的父类)

package com.tong;//这是所有测设类的父类public class People {    private int age;//    这是用于测试的受保护的属性    protected String name;    public int getAge() { return age;    }    public void setAge(int age) { this.age = age;    }    public String getName() { return name;    }    public void setName(String name) { this.name = name;    }//    这是用于测试的受保护的方法    protected void play(){    }}

2.Teacher类,继承了People类,且和People类在同一个包下

package com.tong;//这是一个和父类同包下且继承父类的测试类public class Teacher extends People{    public static void main(String[] args) { People people = new People(); people.name = "people"; people.play();  Teacher teacher = new Teacher(); teacher.name = "teacher"; teacher.play(); //所有代码都能编译通过,表示同包下子类可以直接通过父类实例访问父类的受保护成员    }}

3.Cooker类,和People类在同一个包下,但没有继承关系

package com.tong;//这是一个和父类同包下但没有继承关系的测试类public class Cooker {    public static void main(String[] args) { People people = new People(); people.name = "people"; people.play();  Teacher teacher = new Teacher(); teacher.name = "teacher"; teacher.play(); //上面的代码表示同包下哪怕没有继承关系也可以访问同包下的类的受保护属性  Cooker cooker = new Cooker(); cooker.name = "cooker";//编译错误,没有继承父类,所以Cooker类没有name属性    }}

4.Student类,继承了People类,但不合People类在同一个包下

package com.yi;import com.tong.People;import com.tong.Teacher;import com.tong.Cooker;//这是一个和父类不同包但有继承关系的测试类public class Student extends People{    public static void main(String[] args) { People people = new People(); people.name = "people";//编译失败,不能通过父类实例访问受保护属性 people.play();//编译失败,不能通过父类实例访问受保护方法  Teacher teacher = new Teacher(); teacher.name = "teacher";//编译失败.不能访问异包的类的受保护属性 teacher.play();//编译失败.不能访问异包的类的受保护方法  Student student = new Student(); student.name="student";//编译通过 student.play();//编译通过 //上面两行代码编译通过表示异包的子类只可以访问自己的受保护属性,而不可以访问父类的受保护属性和异包下其他继承父类的子类的受保护属性    }}

这和大部分给出的定义相违背,因为父类中用protected修饰的成员,如果继承这个类的子类与这个类不在同一个包下,那么子类就不能访问父类中用protected修饰符修饰的成员。而是只可以访问自己的受保护成员

也就是子类和父类在不在同一个包中对于父类protected修饰的成员访问权限是不同的。
子类与父类在同一包中:被声明为 protected 的成员能被同一个包中的任何其他类访问;
子类与父类不在同一包中:那么在子类中,子类只可以访问其从父类继承而来的自己的protected成员,而不能访问父类实例以及和父类在同一个包下的其他子类实例的protected成员。

很典型的一个例子就是Object的clone()方法,这个方法只能允许对象克隆自己的对象,而不能克隆Object对象,因为所有对象的clone方法都是继承的Object类的clone方法,但是这个方法是peotected修饰的,它的可见性是Object的所有子类和java.lang包但是异包子类不能直接访问父类的受保护成员

关于protected成员的调用时是否有访问权限的问题
首先要确定出该protected成员出自哪个类这个类在哪个包中,然后才可以得出这个protected成员的可见性范围是什么,然后就可以判断出当前用法是否可行了。