封装是面向对象的核心特征之一,它提供了一种信息隐藏技术。类的包装包含两层含义:一是将数据和对数据的操作组合起来构成类,类是一个不可分割的独立单位;二是类中既要提供与外部联系的接口,又要尽可能隐藏类的实现细节。封装性为软件提供了一种模块化的设计机制,设计者提供标准化的类模块,使用者根据实际需求选择所需的类模块,通过组装模块实现大型软件系统。各模块之间通过接口衔接和协同工作。
类的设计者和使用者考虑问题的角度不同,设计者需要考虑如何定义类中的成员变量和方法,如何实际其访问权限问题。类的使用者只需要知道有哪些类可以选择,每个类有哪些功能,每个类中有哪些可以访问的成员变量和成员方法等,而不需要考虑了解其实现的细节。
1.类成员的访问权限
按照类的封装性原则,类的设计者既要提供类与外部的联系方式,又要尽可能隐藏类的实现细节,具体办法就是为类的成员变量和成员方法设置合理的访问权限。
Java为类设置了两种访问权限,为类的成员变量和成员方法设置了四种访问权限。它们是public(公有),protected(保护),默认和private(私有)。
①、public:被public修饰的成员变量和成员方法可以在所有类中访问。所谓在某类中访问某成员变量,是指在该类的方法中给该成员变量赋值和取值。所谓在某类中访问成员方法,是指在该类的方法中调用该成员方法。所以在所有类的方法中,可以使用被public修饰的成员变量和成员方法。
②、protected:被protected修饰的成员变量和成员方法可以在声明它的类中访问,可以在该类的子类中访问,也可以在与该类位于同一个包中的类访问,但不能在位于其他包的非子类中访问。
③、默认:默认指不使用(即省略)权限修饰符。不使用权限修饰符修饰的成员变量和成员方法可以在声明它的类中访问,也可以在与该类位于同一个包中的类访问,但不能在位于其他包中的类访问。
④、private:private修饰的成员变量和成员方法只能在声明它们的类中访问,而不能在其他类(包括子类)中访问。
2.四种权限修饰符的对比如下表所示:
内容 | public | protected | 默认 | private |
同类访问 | √ | √ | √ | √ |
同包其他类访问 | √ | √ | √ | × |
同包子类访问 | √ | √ | √ | × |
不同包子类访问 | √ | √ | × | × |
不同包非子类访问 | √ | × | × | × |
3、getter/setter访问器
在Java中,通常会将属性私有化,然后提供一对public的getter和setter方法对私有属性进行访问。getter方法和setter方法称为属性访问器。例如:
package jackWe; public class Student { //类的属性定义 private String name; private int age; private String favourite; //构造函数 public Student() { } //属性访问器 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getFavourite() { return favourite; } public void setFavourite(String favourite) { this.favourite = favourite; } public void introduce(){ System.out.println("大家好,我是"+this.name+",我今年"+this.age+"岁,我的爱好是"+this.favourite); } protected void study(){ System.out.println("我正在学习"); } void dowork(){ System.out.println("正在做作业"); } }
package jackWeTest; import jackWe.Student; public class StudentTest { /** * 让student访问公有的getter和setter访问器为name、age、favourite属性赋值 * @param args */ public static void main(String[] args) { Student student = new Student(); student.setName("JackWe"); student.setAge(18); student.setFavourite("篮球"); student.introduce(); } }
从上例可以看出,Student类与StudentTest类是不同包非子类,在StudentTest类中通过创建Student类的对象student通过公有的setter方法给私有的属性赋值。并且student对象无法调用protected修饰的study方法和默认的dowork方法。
4、类的访问权限
声明一个类只能使用public和省略权限访问修饰符两种。不能使用protected和private。虽然一个Java源文件可以定义多个类,但只能有一个类能够使用public修饰符,该类的类名与类文件的文件名必须相同。例如:
package jackWeTest; public class StudentTest { /** * 在StudentTest类中创建Student静态类的student对象 * @param args */ public static void main(String[] args) { Student student = new Student(); student.setName("JackWe"); student.setAge(18); student.setFavourite("篮球"); student.introduce(); } static class Student{ //类的属性定义 private String name; private int age; private String favourite; //构造函数 public Student() { } //属性访问器 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getFavourite() { return favourite; } public void setFavourite(String favourite) { this.favourite = favourite; } public void introduce(){ System.out.println("大家好,我是"+this.name+",我今年"+this.age+"岁,我的爱好是"+this.favourite); } protected void study(){ System.out.println("我正在学习"); } void dowork(){ System.out.println("正在做作业"); } } }
如上例,StudentTest类为public修饰,Student类为默认的,并且为静态类。