01封装概述
说到封装,我最喜欢举的例子就是随开随用的手机
只需要按一下开机键,动动手指就可以了,作为用户的我们根本没必要了解其中的电路板怎么设置,也没必要了解硬件之间如何连接.手机制造商把复杂的内部细节封装起来,只给我们几个基础的按键和屏幕,工作原理我们不需要知道,只要能用就行
需要用户使用的部分暴露出来,不需要用户操作和知道的全部隐藏起来,这就是封装.
从程序的角度上来说就是封装把对象的属性和方法结合成一个整体,尽可能的隐藏对象内部的方法和实现细节
对于开发人员来说,要追求**“高内聚,低耦合”,**
高内聚就是类的内部数据操作及细节自己完成,不需要也不允许外部干涉
低耦合就是仅暴露少量方法给外部使用,能方便外部调用就好
封装优点
1.提高代码的安全性
2.提高代码的复用性
3.“高内聚”:封装细节,便于修改内部代码,提高可维护性
4.“低耦合”:简化外部调用,便于使用者使用,便于扩展和协作
代码演示:
没有封装的代码的缺点
class Person {
String name;
int age;
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
public class Test {
public static void main(String[] args) {
Person p = new Person();
p.name = "小红";
p.age = -45;//年龄可以通过这种方式随意赋值,没有任何限制
System.out.println(p);
}
}
显然没有封装的代码,用户可以随意更改其中的内容从而显示出不和常规逻辑的内容,所以就要对代码进行封装,在内部作出限制,如何封装,后续内容讲完在给出封装代码
02封装的实现-使用访问控制符
java的封装是通过使用"访问控制符"来进行的,这些访问控制符控制着内部细节的隐藏和暴露,
四种访问控制符
1. private
表示私有,只有自己类能访问
2. default
表示没有修饰符修饰,只有同一个包的类能访问
3. protected
表示可以被同一个包的类以及其他包中的子类访问
4. public
表示可以被该项目的所有包中的所有类访问
四种访问控制符,分别代表着不同的权限,我们利用他们可以尽可能的细化控制,从而提高安全性
1.类的三大成员都可以使用四个访问修饰符
2.private修饰的成员变量不能被继承
3.default修饰的成员 同包可继承 异包不可继承
4.protected 修饰的成员变量 同包异包都可继承
5.public 修饰的 怎么都能继承
6.外部类只能使用public default 修饰
7.内部类可以使用四个访问修饰符
日常使用
一般我们使用最多的是private访问权限
使用private权限的时候时候需要提供相应的get/set 方法来访问相关属性,这些方法通常由public修饰,以提供对属性的赋值和读取操作
(注意点:boolean变量的get方法是is开头的)
使用的时候注意,一些只用于本类辅助性的方法可以用private修饰,希望其他类调用就要用public修饰
代码示例
加粗样式JavaBean的封装示例
public class Person {
// 属性一般使用private修饰
private String name;
private int age;
private boolean flag;
// 为属性提供public修饰的set/get方法
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 boolean isFlag() {
// 注意:boolean类型的属性get方法是is开头的
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
看完这个是不是有点感悟了呢
来,我们解决一下年龄赋值的问题
class Person {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
// this.age = age;//构造方法中不能直接赋值,应该调用setAge方法
setAge(age);
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
//在赋值之前先判断年龄是否合法
if (age > 130 || age < 0) {
this.age = 18;//不合法赋默认值18
} else {
this.age = age;//合法才能赋值给属性age
}
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}
public class Test2 {
public static void main(String[] args) {
Person p1 = new Person();
//p1.name = "小红"; //编译错误
//p1.age = -45; //编译错误
p1.setName("小红");
p1.setAge(-45);
System.out.println(p1);
Person p2 = new Person("小白", 300);
System.out.println(p2);
}
}
通过这样的一个案例我们就可以看到,用户赋值的年龄是有区间的,当然用户自己不知道,这样的程序就满足了封装的高内聚和低耦合的特征