封装(Encapsulation)是面向对象的三大特征之一(另两个是继承和多态),指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象的内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。
将客观世界用对象来描述,相当于造了一个箱子。封装则是给箱子上了个锁,然后开了几个窗。从此之后,要么用锁开(成员类),要么通过这几个窗子来访问箱子内部的东西。
封装的好处都有啥:
- 向别人隐藏类的实现细节;
- 限制外来者对成员变量不合理的访问
- 便于修改,提高代码的可维护性。
良好的封装遵循下述原则:
- 把成员变量和方法的实现细节隐藏起来;
- 把供外人使用的方法暴露出来。
和C++类似,Java使用private, protected, public
三个访问控制符,表示3个访问控制级别(权限),再加上一个没有任何访问控制符的级别(default),一共4个级别。
- private(当前类访问权限):只能在当前类的内部被访问,主要用来修饰成员变量;
- default(包访问权限):可以被相同包下的其他类访问;
- protected(子类访问权限):既可以被同一个包的其他类访问,也可以被不同包中的子类访问(主要用于继承);
- public(公共访问权限):可以被所有类访问。
在C++的基础上,Java的访问控制多了一个级别,default,这是由于Java独特的**包(package)**机制导致的。
private | default | protected | public | |
---|---|---|---|---|
同一个类 | √ | √ | √ | √ |
同一个包 | √ | √ | √ | |
子类 | √ | √ | ||
全局范围 | √ |
局部变量作用域就是它所在的方法或代码块,不可能被其他类访问。因此,局部变量没有控制访问修饰。
外部类可以使用访问控制符修饰,但因为它处于当前类的外部,因此private
和protected
没啥意义,所以只有public
和default
两种。
如果一个Java源文件中,所有的类都没有public修饰,那这个源文件的文件名可以是任意名称;但是一旦有一个类被修饰为
public
,这个源文件必须用这个类的类名。
public class Person
{
private String name;
private int age;
public void setName(String name)
{
if (name.length > 6 || name.length < 2)
{
System.out.println("输入的人名不符合要求");
}
else
{
this.name = name;
}
}
public String getName()
{
return this.name;
}
// TODO
}
- 因为Peson类用
public
修饰了,所以这个类所在的文件必然是“Person.java”。
从外来者使用的视角,发现:
- 这个类的成员变量,name和age不能直接访问了,需要通过它提供的set和get函数来间接访问了;
- 方法的实现细节不重要了,外来者只关注能否达到自己的目的就行。
public class PersonTest
{
public static void main(String[] args)
{
var p = new Person();
p.name = "王五"; // Error,age被封装起来了,不能直接访问
p.setName("王五");
System.out.println(p.name); // Error
System.out.println(p.getName());
}
}