12.1 访问控制概述
访问控制(Access Control)修饰符用于控制代码访问其修饰目标的权限,之前我们见过最多的是 public。
Java中提供了4种访问控制范围(或成为访问级别),从大到小依次为:公开、受保护、默认(包内私有)、私有,下表是他们对应的关键字及控制范围简要描述(除了默认级别没有关键字,其它3个都有对应的关键字):
| 访问控制修饰符 | 修饰目标 | 控制范围 |
|---|---|---|
| public | 顶层类型(类,接口等),属性,方法,内部类型(内部类、接口等) | 所有的代码都可以访问 |
| protected | 属性,方法,内部类型(内部类、接口等) | 本包及其子类(继承)可访问 |
| 默认 | 顶层类型(类,接口等),属性,方法,内部类型(内部类、接口等) | 本包的代码可访问 |
| private | 属性,方法,内部类型(内部类、接口等) | 本类代码可访问 |
12.2 public
公开的访问控制使用public关键字,该关键字可以修饰顶层元素,如类,接口,枚举,记录,注解等,还可以修饰属性、方法或内部类/接口等。比如之前我们经常见到的写法:
public class PublicClass{
public int num = 1;
public void printNum(){
System.out.println(num);
}
}
由于public修饰的元素是在项目中所有位置都能访问到,一般修饰最多的是类及方法。属性极少使用public修饰,这与封装有关。
12.3 protected
受保护的访问范围 ,修饰 的目标只能本包访问或子类访问,比如声明以下的类:
package com.laotan.article12;
public class ProtectedClass {
protected int num = 1;
protected void print() {
System.out.println(num);
}
}
上面的类中声明了两个受保护的成员,如果在其它包的类中访问是不允许的:
package com.laotan.article12.sub;
import com.laotan.article12.ProtectedClass;
public class ProtectedClassTest {
static void main() {
ProtectedClass protectedClass=new ProtectedClass();
System.out.println(protectedClass.num); // 报错
}
}
在另一个包访问受保护的 num 会提示:
'num' has protected access in 'com.laotan.article12.ProtectedClass'
要注意的是,就算是不同包中的子类按照上述方式访问也是不成立的:
package com.laotan.article12.sub;
import com.laotan.article12.ProtectedClass;
public class ChildProtectedClass extends ProtectedClass {
public void printNum() {
ProtectedClass protectedClass = new ProtectedClass();
System.out.println(protectedClass.num); // 与上一个例子报一样的错误
}
}
实际上对于子类中可访问受保护的成员,应该从继承的角度理解,即受保护的成员能被继承到子类,既然如此,子类直接访问即可:
package com.laotan.article12.sub;
import com.laotan.article12.ProtectedClass;
public class ChildProtectedClass extends ProtectedClass {
public void printNum() {
System.out.println(num);
}
}
这样调用才是符合 Java 语法的。
12.4 default
默认访问控制范围也叫包基本的访问控制,这种访问级别并没有对应的关键字,比如:
package com.laotan.article12;
class DefaultDemo {
}
在class关键字前没有其他修饰符,这个类就只能在与之同包的代码中被使用到,如果在其他包中访问,比如:
package com.laotan.article12.sub;
import com.laotan.article12.DefaultDemo;
public class DefaultClassTest {
static void main() {
DefaultDemo defaultDemo = new DefaultDemo(); // 报错
}
}
会出现以下错误信息:
'com.laotan.article12.DefaultDemo' is not public in 'com.laotan.article12'. Cannot be accessed from outside package
虽然两个类所在的包似乎有父子关系,在在Java中这种所谓的“父子包”并没有语法上的支持,它们实际上毫无关系。这也导致两个类是在不同的包中,那么出错就是因为违反了默认访问控制的约束。如果DefaultClassTest类和DefaultDemo在同一个包中就没问题了。
如果类是public的,其中的成员是默认访问级别的,在包外也是不能访问到的:
package com.laotan.article12;
public class DefaultDemo {
int num = 1; // 默认访问级别的变量
void print() {
System.out.println(num);
}
}
在子包中访问:
package com.laotan.article12.sub;
import com.laotan.article12.DefaultDemo;
public class DefaultClassTest {
static void main() {
DefaultDemo defaultDemo = new DefaultDemo();
System.out.println(defaultDemo.num); // 报错
defaultDemo.print(); // 报错
}
}
同样出现类似的出错信息:
'num' is not public in 'com.laotan.article12.DefaultDemo'. Cannot be accessed from outside package
12.5 private
私有访问控制对应的关键字private可以修饰属性,方法及内部类,其被访问到的范围最小,被修饰的成员只能在本类中被访问,通常用于修饰属性达到封装之目的。
public class Dog {
private int age; // 年龄
private float weight; // 体重
private String breed; // 品种
private String color; // 毛色
private void print() {
System.out.println("age:" + age);
}
}
上面的类声明中,4个属性及1个方法都是private修饰的,意味着在其它类中不能访问到它们。
12.6 访问控制应用-POJO
POJO (Plain Old Java Object)是指简单的 Java 对象,它通常没有实现特定的接口或继承特定的类。POJO 的设计原则是简单、普通、纯粹的 Java 对象,不依赖于特定的框架或技术。POJO 通常用于封装数据,可以包含一些私有字段(属性)和公共的 getter 和 setter 方法,用于对属性进行读写操作。主要用途包括:数据传输,数据存储,数据交换,单元测试等。
它的实现要求:
- 类必须是具体的和公共的
- 具有无参数的构造方法
- 属性被private修饰
- 为每一个属性提供一对public的getter与setter方法
- 只读属性只提供getter方法,只写属性只提供setter方法
方法命名规则:
- 非布尔类型属性,如 String name,使用这样的方法命名:setName、getName
- 布尔类型属性,如 boolean exist,使用:setExist,isExist
典型示例如下:
public class Dog {
private int age; // 年龄
private float weight; // 体重
private String breed; // 品种
private String color; // 毛色
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public float getWeight() {
return weight;
}
public void setWeight(float weight) {
this.weight = weight;
}
public String getBreed() {
return breed;
}
public void setBreed(String breed) {
this.breed = breed;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
声明的 getter 与 setter 方法可以使用IDEA产生,也可以借助于Lombok开源包,减少getter与setter这样的模板代码
使用时,调用setter方法为实例的属性赋值,使用getter方法获取实例的属性值:
Dog erHa1 = new Dog();
erHa1.setAge(3);
erHa1.setWeight(2.4F);
erHa1.setBreed("西伯利亚哈士奇");
erHa1.setColor("灰色");
System.out.println(erHa1.getAge());
System.out.println(erHa1.getWeight());
System.out.println(erHa1.getBreed());
System.out.println(erHa1.getColor());
12.7 小结
本小节介绍了Java中的访问控制修饰符,Java中提供了4种访问控制范围:public、protected、默认(无修饰符)、private。public常用于修饰类和方法、protected适用于子类继承场景、默认访问控制用于包内共享、private主要用于封装属性。还介绍了访问控制的典型应用-POJO。访问控制是Java封装特性的重要实现方式,合理使用可以提高代码的安全性和可维护性。
6016

被折叠的 条评论
为什么被折叠?



