封装
封装:将一些需要的字段或方法,使用private关键字进行修饰,同时提供对应的get方法和set方法来提供给外部。
封装的意义:
- 数据的安全性。
- 类的调用者对类的使用成本降低了,相应的开发效率更高。
我们先看一个不进行封装的代码:
Person类
class Person {
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Test类
public class Test {
public static void main(String[] args) {
Person person = new Person("张三",18);
System.out.println("我叫" + person.name + ", 今年" + person.age + "岁");
}
}
运行结果如下:
这样的代码很有弊端:
- 调用者必须了解类的内部实现,才能使用这个类,导致学习这个类的成本大大提高。
- 一旦类的实现者修改了部分代码(例如将name改成myName),这使得调用者要花费大量的精力来更改代码。
下面用封装的形式来实现上例代码:
Person类
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public void show() {
System.out.println("我叫" + name + ", 今年" + age + "岁。");
}
}
Test类
class Test {
public static void main(String[] args) {
Person person = new Person("张三", 18);
person.show();
}
}
运行结果如下:
封装后:
- 此时类的调用者不能直接使用私有字段,而需要借助公有方法 show 方法,而且此时类的调用者根本不必了解 Person 类的实现细节。
- 如果类的实现者修改了部分代码(例如将name改为myName), 此时类的调用者不需要做任何修改。
封装后,我们不能直接访问私有字段,但是我们可以通过公有方法 setter / getter 方法来获得设置和获得私有字段的属性。
Person类
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
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;
}
}
Test类
class Test {
public static void main(String[] args) {
Person person = new Person();
person.setName("张三");
person.setAge(18);
System.out.println("我叫" + person.getName() +
",今年" + person.getAge() + "岁。");
}
}
运行结果如下:
- 上例的 setName/getName 方法就是私有变量 name 的 setter / getter 方法。
- 可以看出可以通过 setter / getter 方法可以设置和获得私有字段的属性,但是并不是所有的私有字段都要有 setter / getter 方法,要根据实际情况而定,用不到的时候就没有必要去定义该方法。
另外,封装时,可以在 setter 方法中添加约束,使得私有字段更加的安全。
例:
Person类
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public Person() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age < 0) {
System.out.println("年龄不能为负数!");
return;
}
this.age = age;
}
}
Test类
class Test {
public static void main(String[] args) {
Person person = new Person();
person.setName("张三");
person.setAge(-18);
System.out.println("我叫" + person.getName() +
",今年" + person.getAge() + "岁。");
}
}
运行结果如下:
从上例中,可以看出私有变量 age 并没有被赋值,而是默认初始化的值,因为 setter 方法对 age 变量存在约束,这也使得数据变得更加安全合理。