什么是封装?
封装是指在将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部的信息,而是通过该类所提供的方法来实现对内部信息的操作和访问
封装的作用
-
隐藏类的实现细节
-
让使用者只能通过事先预定的方法来访问数据,从而可以在该方法里加入控制逻辑,限制堆成员变量的不合理访问
-
可以进行数据检查,,从而有利于保证对象信息的完整性
-
便于修改,提高代码的可维护性
-
减少耦合:可以独立的开发、测试、优化、使用
-
便于调节性能,可以通过剖析确定哪些模块影响了系统的性能
-
降低了构建大型系统的风险:即使整个系统不可用,但是这些独立的模块可能是可用的
不封装可能出现问题
class Student{//姓名String name;//年龄int age;//show()方法,显示所有成员变量public void show(){System.out.println("姓名:"+name);System.out.println("年龄:"+age);}}
class StudentDemo{public static void main(String[] args){//创建学生对象Student s=new Student();s.show();System.out.println("-----------");//给成员变量赋值s.name="林青霞";s.age=16;s.show();System.out.println("-----------");//给age重新赋值s.age=-27;//数据不合理 s.show();System.out.println("-----------");}}
通过示例可以发现,通过对象给成员变量赋值,常常可以赋值一些非法的数据,在现实场景中常常是不合理的
对数据进行判断,可以在构造方法,可以在普通方法,但是如果是较为复杂的逻辑,在构造方法中就会存在很大的问题
因此,对于这种情况,我们常常是限制用户对成员变量的使用权限,而是提供一个开放的方法, 用于将用户传递进来的数据做数据处理或逻辑判断后,再赋值给对象
示例:该动物园新来了一个动物,添加了编号、姓名、年龄、种类、品种,需要存储到数据库进行保存
package com.carl.javacore.encapsulation;/*** @PackageName com.carl.javacore.encapsulation* @Auther carl* @Description: TODO* @Version V1.0* @Date 2022-09-12 16:38* Modified By:TODO**/public class Animal {/*** 编号*/private String id;/*** 姓名*/private String name;/*** 年龄*/private Integer age;/*** 种类*/private String type;/*** 品种*/private String varieties;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {if(age>100 || age<0){//抛出异常System.out.println("该变量赋值不合法!");//使用输出的方式代替异常的输出return;}this.age = age;}public String getType() {return type;}public void setType(String type) {this.type = type;}public String getVarieties() {return varieties;}public void setVarieties(String varieties) {this.varieties = varieties;}@Overridepublic String toString() {return "Animal{" +"id='" + id + '\'' +", name='" + name + '\'' +", age=" + age +", type='" + type + '\'' +", varieties='" + varieties + '\'' +'}';}
}
public class Test {public static void main(String[] args) {Animal a=new Animal();a.setId("8790");a.setName("巴顿");a.setAge(-24);a.setType("猫");a.setVarieties("蓝白");//然后将这个对象调用Mybatis的insert方法存储System.out.println(a);//这里通过输出的方式代替存储的操作}
}
输出结果:
该变量赋值不合法!
Animal{id='8790', name='巴顿', age=null, type='猫', varieties='蓝白'}
通过这种方式,我们确实可以避免用户保存脏数据,因为脏数据的存在极大可能性会导致程序的崩溃,因此封装是必要的
封装的原则
-
将不需要对外提供的内容都隐藏起来
-
把属性隐藏,提供公共方法对其访问
访问权限控制符
Java提供了四个访问权限控制符:private、public、protected、default,分别代表四个访问控制级别,控制级别由小到大
private | default | protected | public | |
---|---|---|---|---|
同一个类中 | √ | √ | √ | √ |
同一个包中 | √ | √ | √ | |
子类中 | √ | √ | ||
全局范围内 | √ |
-
private:当前类访问权限
如果类里的一个成员(包括成员变量、方法和构造器等)使用private访问控制符来修饰,则这个成员只能在当前类的内部被访问,一般用于修饰成员变量和一些不愿意暴露给其他类访问的方法
-
protected:子类访问权限
如果一个成员(包括成员变量、方法和构造器等)使用protected修饰,那么这个成员既可以被同一个包中的其他类访问,也可以被不同包中的子类访问,通常情况下,使用protected修饰的目的是希望其子类来重写这个方法
-
default:包访问权限
如果类中的一个成员(包括成员变量、方法和构造器等)或一个外部类不使用任何访问控制符修饰,就称它为包访问权限,default访问控制的成员或外部类可以被相同包下的其他类访问
Java8 中也作用于声明接口函数的默认实现
-
public:公共访问权限
最大的访问控制级别,如果一个成员(包括成员变量、方法和构造器等)或者一个外部类使用public访问控制符修饰,那么这个成员或外部类就可以被所有类访问,不管访问类和被访问类是否处于同一个包,是否具有父子继承关系