文章目录
6.1 封装
6.1.1 封装的概述
6.1.1.1 为什么要封装
我要用洗衣机,只需要按一下开关和洗涤模式就可以了。有必要了解洗衣机内部的结构吗?有必要碰电动机吗?
我们使用的电脑,内部有CPU、硬盘、键盘、鼠标等等,每一个部件通过某种连接方式一起工作,但是各个部件之间又是独立的
现实生活中,每一个个体与个体之间是有边界的,每一个团体与团体之间是有边界的,而同一个个体、团体内部的信息是互通的,只是对外有所隐瞒。
-
面向对象编程语言是对客观世界的模拟,客观世界里每一个事物的内部信息都是隐藏在对象内部的,外界无法直接操作和修改,只能通过指定的方式进行访问和修改。
封装可以被认为是一个保护屏障,防止该类的代码和数据被其他类随意访问。适当的封装可以让代码更容易理解与维护,也加强了代码的安全性。
-
随着系统越来越复杂,类会越来越多,那么类与类之间范文的边界要如何把握。面向对象的开发原则”高内聚,低耦合“,而”高内聚,低耦合“的体现之一:
隐藏对象内部的复杂性,对外公开简单和可控的访问方式
,从而提高代码的可扩展性和可维护性。通俗来讲就是把该隐藏的隐藏,该暴露的暴露,这就是封装的设计思想。- 高内聚:尽可能的让一个模块内部的代码相关程度高,相互联系紧密。模块内代码相互联系越紧密,内聚就越高,模块独立性就越好。一个模块尽量去独立的完成一个功能
- 低耦合:尽可能地将每一个功能通过模块单独去完成,然后通过指定的接口来相互联系,联系越少耦合度越低。
6.1.1.2 如何实现封装
- 实现封装就是控制类或成员的可见范围,需要依赖访问控制修饰符(也称权限修饰符)来控制
- 权限修饰符:
public、protected、缺省、private
- 外部类能访问:public、缺省
- 成员变量、成员方法、构造器、成员内部类能访问:public、protected、缺省、private
6.1.2 成员变量/属性私有化问题
成员变量(field)私有化后,需要提供标准的get/set
方法,我们把这种成员变量称之为属性
(property)。
或者可以说只要能通过
get/set
操作的就是事物的属性,哪怕它没有对应的成员变量。
6.1.2.1 成员变量封装的目的
隐藏类的实现细节
- 让使用者是能通过事先预定的房啊来访问数据,从而可以在方法中加入控制逻辑,控制对成员变量的不合理访问。还可以进行数据检查,从而有利于保证对象信息的完整性。
- 便于修改,提高代码的可维护性。对于隐藏部分,如果其在内部进行了修改,而对外可以访问的方式不变的话,根本不会感觉到它的修改。如Java9中,将String的底层从char[]改为byte[],而对外的方法不变,使用者如果不去看源码的话根本很难发现内部进行了修改,也并不会对使用者造成影响。
对外提供公共的访问方式
6.1.2.2 实现步骤
使用private修饰成员变量
private 数据类型 变量名;
- 提供getXxx/setXxx方法,用来访问成员变量
public class Person {
private String name ;
private int age ;
public void setName(String name1) {
name = name1 ;
}
public void setAge(int age1) {
age = age1 ;
}
public String getName() {
return name ;
}
public int getAge() {
return age ;
}
}
测试:
public class PersonTest {
public static void main(String[] args) {
Person p = new Person() ;
p.setName("张三");
p.setAge(21);
System.out.println("name = " + p.getName());
System.out.println("age = " + p.getAge());
}
}
6.1.3 this关键字
在实例方法中可以使用this关键字调用当前对象的成员
- this:在实例方法中,表示调用该方法的对象引用
- 可以用来区分成员变量和局部变量
- 在没有歧义的情况下,this可以省略
6.1.3.1 局部变量和实例变量重名
未使用this关键字
public class Person {
private String name ;
private int age ;
public void setName(String name) {
name = name ;
}
public void setAge(int age) {
age = age ;
}
public String getName() {
return name ;
}
public int getAge() {
return age ;
}
}
public class PersonTest {
public static void main(String[] args) {
Person p = new Person() ;
p.setName("张三");
p.setAge(21);
System.out.println("name = " + p.getName());
System.out.println("age = " + p.getAge());
}
}
使用this关键字
public class Person {
private String name ;
private int age ;
public void setName(String name) {
this.name = name ;
}
public void setAge(int age) {
this.age = age ;
}
public String getName() {
return name ;
}
public int getAge() {
return age ;
}
}
public class PersonTest {
public static void main(String[] args) {
Person p = new Person() ;
p.setName("张三");
p.setAge(21);
System.out.println("name = " + p.getName());
System.out.println("age = " + p.getAge());
}
}
6.1.3.2 this关键字在构造器中使用
同一个类中的构造器互相调用
- this():表用本类中的无参构造
- this(实参列表):调用本类的有参构造
- this()和this(实参列表) 只能出现在构造器首行
- 不能出现递归调用
案例:
public class Student {
private String name ;
private int age ;
public Student() { // 无参构造方法
}
public Student(String name) { // 一参
this() ; // 调用无参构造
this.name = name ;
}
public Student(String name , int age) {
this(name) ;
this.age = age ;
}
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 void getInfo() {
System.out.println("Student{" +
"name='" + name + '\'' +
", age=" + age +
'}');
}
}
class StudentTest {
public static void main(String[] args) {
Student student = new Student("张三" , 23);
student.getInfo();
}
}
6.1.4 给成员变量赋值的两种方式
6.1.4.1 setXxx()方法
通过对象调用setXxx()
方法对成员变量进行赋值、修改
6.1.4.2 构造器
构造器只能对成员变量进行初始化
,无法使用它对成员变量进行修改
案例:
public class Student {
private String name ;
private int age ;
public Student() { // 无参构造方法
}
public Student(String name , int age) {
this.name = name ;
this.age = age ;
}
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 void getInfo() {
System.out.println("Student{" +
"name='" + name + '\'' +
", age=" + age +
'}');
}
}
class StudentTest {
public static void main(String[] args) {
Student student1 = new Student("张三" , 23);
Student student2 = new Student() ;
student2.setName("李四");
student2.setAge(25);
student1.getInfo();
student2.getInfo();
// 使用set方法对student1对象的成员变量的值进行修改
student1.setName("王五");
student1.getInfo();
}
}
6.1.5 IDEA自动生成getter/setter方法
快捷键 : Alt + Insert
public class Student {
String name ;
int age ;
String gender ;
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 getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
6.1.6 IDEA生成构造器
public class Student {
String name ;
int age ;
String gender ;
public Student() {
}
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
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 getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}