访问修饰符,即对访问范围的控制。在Java中,有以下几种访问修饰符:
1.对类而言:
(1)public:在所有的包中均可见
(2)default(默认):只在该类所在包中可见
注:类不能用private和protected来修饰
2.对成员变量和成员方法而言:
(1)public:在所有包中均可见(且可调用)
(2)protected:包内所有类中均可见(且可调用),包外有继承关系的子类可见(仅可在子类内部调用)
(3)private:只在同一个类中可见(且可调用)
(4)default(默认):
注意:
在同一个包中,尽管是protected的方法和属性,包内的任何类都可以访问到。
在父类和子类不在同一个包中的前提下,对于子类来说,子类继承了父类所有的属性和方法(任何访问修饰符),虽然对从父类继承来的protected的属性和方法可见,但是只能在子类的内部进行访问,即:(this.)方法名、(this.)属性名进行访问和操作,而无法在外部对子类进行实例化,并用子类对象.protected方法或属性来访问。
举个简单的例子,我们都知道Object类是所有类的父类,而在Object中有一个叫clone()的方法,那我们在实例化对象后能调用这个函数吗?通过实践证明是不可以的,给出的错误提示是:The method clone() from the type Object is not visible.该方法是不可见的,这就类似于我们刚刚提到的,虽然子类从父类中继承过来了包括protected的方法和属性,但对于外部的类(包括main函数中)都是无法获取到的。
下面,再通过一个简单的例子来说明这个问题:
首先,在同一个项目中创建两个包test.demo1和test.demo2,然后在test.demo1包中分别创建三个类Parent、Child和Test类,并让Child类去继承Parent类,然后再test2.demo2中再去分别去创建两个Child类和Test类,这个Child类也让它继承test.demo1中的Parent类。结构如下图所示:
然后我们对这几个类进行一些对属性和方法的操作:
test.demo1中:
Parent类:
package test.demo;
public class Parent {
protected int num = 10;
protected void method(){
System.out.println("父类的method方法");
}
}
Child类:
package test.demo;
public class Child extends Parent{
}
Test类:
package test.demo;
public class Test {
public static void main(String[] args) {
Child child = new Child();
System.out.println(child.num);
}
}
运行Test中的main方法时没有报错,正确显示了结果:10
Child类:
package test.demo1;
import test.demo.Parent;
public class Child extends Parent{
public Child(){
method();//父类的method方法
}
}
Test类:
package test.demo1;
import test.demo.Parent;
public class Test {
Parent p;
public void fun(){
}
public static void main(String[] args) {
Child child = new Child();
}
}
由此可见,test.demo2包中Child对象继承了父类中的method方法,并在构造函数中成功调用。现在我们来对以上代码进行一些修改:
(1)我们在test.demo2中Test类的main函数中尝试获取Child对象中的num属性会报错,原因在于num的属性是protected的,无法在外部获取和调用。
(2)我们将Parent类中的num属性和method方法的protected去掉,即访问修饰符变为default.结果显示,test.demo1中的Test依然能正常运行,显示结果10,但是在test.demo2中Child类和Test类都报错了,原因是由于父类中的method方法已被修改成了default,而default的方法和属性只能在父类所在的包中被访问,所以,当Child和Parent不在同一个包中,就算是在子类内部也无法访问到默认访问修饰符的属性和方法。