访问修饰符(Access Modifier)
**访问控制修饰符(Access Modifier)**用来定义类、类的方法或者类的成员变量。
我们通过下面的例子来说明:
public class className {
// ...
}
private boolean myFlag;
static final double weeks = 9.5;
protected static final int BOXWIDTH = 42;
public static void main(String[] arguments) {
// 方法体
}
Java中有三种访问修饰符,分别是public、protected和private,不带任何修饰符则称之为default。
Java的访问权限控制只存在于编译阶段,而编译生成的字节码文件事实上没有留下任何痕迹,只是在编译的时候进行访问权限的检查。
因此,通过反射的手段,可以访问任何包下任何类的成员,例如,访问类的私有成员也是没问题的。
public
被public修饰的类、类的方法或者类的成员变量,它具有最大的被访问权限。
protected
被protected修饰的类的方法或者类的成员变量, 对同一包内的类,或者其所有的子类内部可见。
分析1
这里说,被protected修饰的类的方法或者类的成员变量,对所有的子类内部可见,是指在子类中的构造函数、成员方法中,能够访问到这些被protected修饰的类的方法或者类的成员变量。
然而,通过这个子类的实例对象,是无法访问到这个被protected修饰的类的方法或者类的成员变量的。
分析2
被protected修饰的类的方法或者类的成员变量, 对所有的子类内部可见。这意味着,无论这些子类是否与父类处于同一个包,这些被protected修饰的类的方法或者类的成员变量,在子类内部都可见。
看下面的例子:
package com.p1;
public class A {
protected void method1() {
}
}
package com.p2;
public class B extends A {
public B() {
// 正确
this.method1();
// 正确
super.method1();
}
}
package sw.test;
public class Test {
public static void main(String[] args) {
A b = new B();
// b.method1(); 错误
A a = new A();
// a.method1(); 错误
}
}
修饰对象:变量、方法。
注意:不能修饰类(外部类)、接口及接口的成员变量和成员方法。
默认访问修饰符-不使用任何关键字
使用默认访问修饰符(即不使用任何关键字)声明的类、类的成员变量或成员方法,对同一个包内的类是可见的。
private
对于被private修饰的类的方法或者类的成员变量,它们的访问范围仅限于类的内部,是一种封装的体现。
例如,大多数的成员变量都是修饰符为private的,因为它们不希望被任何外部的类访问。
声明为private(私有访问类型)的变量只能通过类中公共的 getter 方法被外部类访问。
public class Logger {
private String format;
public String getFormat() {
return this.format;
}
public void setFormat(String format) {
this.format = format;
}
}
注意,外部类和接口不能声明为 private。而内部类天然地需要用private来修饰。
private与final
用private来修饰final方法是没有意义的。
因为声明为final方法的目的,就是不允许子类覆盖这个final方法,然而加上private后,这个方法对于子类而言不具有可见性,谈何覆盖。
private与abstract
用private来修饰abstract方法是错误的,
abstract方法要求在子类中具体来实现它。然而加上private后,这个abstract方法对于子类而言不具有可见性,谈何实现(覆盖)。
private修饰构造函数
使用private修饰构造函数后,将不能在其他类中通过new的方式来实例化一个这个类的对象。
因此,使用private修饰构造函数,能够有效控制对象的创建行为,这在有些设计模式中是非常重要的。
总结
类内部 | 本包 | 子类 | 外部包 | |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | × |
default | √ | √ | × | × |
private | √ | × | × | × |
接口的访问修饰符
接口的访问修饰符只有public和默认(default)。
接口里的成员变量默认都隐式声明为 public static final,而接口里的方法默认情况下访问权限为 public。
接口中的所有方法都是抽象方法,不会有任何实现,而它的具体实现在实现这个接口的具体类中完成。而且,这个接口中的方法是不可更改的。同样的,接口中的变量也是不可更改的。所以,要声明为final。
类的访问修饰符
类的访问修饰符只包括public和默认。类不能被protected和private修饰。
类的默认访问修饰符
当不使用访问修饰符修饰一个类时,这个类只能被同一个包中的类所访问。
比如,有类A:
package com.p1;
class A {
protected void method1() {
}
}
位于另一个包的类B就无法访问到类A了:
public类
一个.java文件中只能有一个public类,并且该文件的文件名,要和这个public类的类名一致。而在这个.java文件中定义的其他的类只能类的默认访问修饰符(default)修饰。
成员变量和成员方法的访问修饰符
private
如果一个类的方法或者变量被private修饰,那么这个类的方法或者变量只能在该类本身中被访问,在类外以及其他类中都不能显示地进行访问。
protected
如果一个类的方法或者变量被protected修饰,对于同一个包中的类,这个类的方法或变量是可以被访问的。
对于不同包的类,只有继承于该类的类,才可以访问到该类的方法或者变量。
public
被public修饰的方法或者变量,在任何地方都是可见的。
访问控制和继承
请注意以下方法继承的规则:
- 父类中声明为 public 的方法,在子类中重写后也必须为 public。
- 父类中声明为 protected 的方法,在子类中重写后,要么声明为 protected,要么声明为 public,不能声明为 private。
- 父类中声明为 private 的方法,不能够被继承。
Reference
- Java 中4种访问修饰符 - public/protected/default(friendly)/private
- Java 修饰符 - http://www.runoob.com/java/java-modifier-types.html
- Java 访问修饰符 - https://www.jianshu.com/p/e81452a19228
- 深入理解 Java 中 protected 修饰符 - https://juejin.im/post/5a1fdfad5188253e2470c20d
- 浅析Java中的访问权限控制 - https://www.cnblogs.com/dolphin0520/p/3734915.html