Java当中的封装
一:封装的概念
把对象的属性和操作(或功能)结合为一个独立的整体,并尽可能隐藏对象的内部实现细节,主要的体现是隐藏性与代码的重用性。一般情况下我们理解概念是 不容易理解的,下面我们可以用简单的例子代码和通俗易懂的话来解释上面的概念。其实java当中的类就是一个体现封装的良好的例子,类是抽象的概念集合,表示的是一 个共性的产物,类之中定义的是属性和行为(方法),比如我们一个一个的人,虽然每个个体都是不一样的,比如兴趣,身高,长相,性格等,但是 所有人都会体现出来共 性,比如都有年龄,身高,眼睛,嘴巴,都会吃饭,都会睡觉等等。所以把人的共性抽象出来,形成概念的集合,我们常常定义一个Person类,其实就是这样的。
二:对概念的理解以及对“隐藏对象的内部细节”与“代码重用性的重点的讲解”
在理解“隐藏对象的内部细节”的概念时,我们必须要弄懂一个概念,就是访问修饰符的问题:
Java面向对象的基本思想之一是封装细节并且公开接口。Java语言采用访问控制修饰符来控制类及类的方法和变量的访问权限,从而向使用者暴露接口,但隐藏实现细节访 问控制分为四种级别:
(1)public: 用public修饰的类、类属变量及方法,包内及包外的任何类(包括子类和普通类)均可以访问;
(2)protected: 用protected修饰的类、类属变量及方法,包内的任何类及包外那些继承了该类的子类才能访问(此处稍后解释),protected重点突出继承;
(3)default: 如果一个类、类属变量及方法没有用任何修饰符(即没有用public、protected及private中任何一种修饰),则其访问权限为default(默认访问权限)。默
认访问权限的类、类属变量及方法,包内的任何类(包括继承了此类的子类)都可以访问它,而对于包外的任何类都不能访问它(包括包外继承了此类的子类)。default重点突出包;
(4)private: 用private修饰的类、类属变量及方法,只有本类可以访问,而包内包外的任何类均不能访问它。
访问级别
访问控制修饰符
同类
同包
子类
不同的包
公开
public
√
√
√
√
受保护
protected
√
√
√
--
默认
没有访问控制修饰符
√
√
--
--
私有
private
√
--
--
--
我们看一段代码:
public class StudentBoKe{
//属性
private String name;
private String number;
private int age;
//setter与getter方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
//是一个姓名与学号验证的函数
public boolean yangZheng(String name,String number){
if(name.equals("小明")&&number.equals("123")){
return true;
}else{
return false;
}
}
//这个是一个A函数
public void A(){
// 在打印System.out.println("这是一个A函数")之前要进行姓名与学号的验证
yangZheng("A","A");
System.out.println("这是一个A函数");
}
//这个是一个B函数
public void B(){
// 在打印System.out.println("这是一个B函数");之前也要进行姓名与学号的验证
yangZheng("B","B");
System.out.println("这是一个B函数");
}
}
我们看到了上面这个类的age这个属性是private访问修饰符且没有提供setter与getter方法,这就意味着,除了在这个类之内访问这个age属性,其外的地方不可以访问这个age, 其他的两个属性name,number同样使用private修饰,为什么就可以在类以外访问呢,这是因为他们都设置了公开的setter与getter方法,虽然我们不可以在类之外使用:new StudentBoKe().name来访问name属性,但是却可以使用new StudentBoKe().getName()来访问name属性,这就叫使用已经敞开的接口,而private的使用则体现了封装的隐藏性。
另一个体现封装的隐藏的一个例子是单例设计模式:
1 public classSingleton{2 //定义一个私有类变量来存放单例,私有的目的是指外部无法直接获取这个变量,而要使用提供的公共方法来获取
3 private static Singleton singleton = null;4 //定义私有构造器,表示只在类内部使用,亦指单例的实例只能在单例类内部创建
5 private Singleton(){}6 //定义一个公共的公开的方法来返回该类的实例
7 public static Singleton getInstance(){8 if(singleton == null){9 singleton = new Singleton();10}11 returnsingleton;12}13 }
该示例中,我们看到它把有一个构造器都给私有化了(隐藏),所以我们不可能使用new Singleton() 的方式再new出一个实例来,那只能够使用getInstance方法来获得一个实例。
我们学习java的时候,往往听说要把一个功能封装成一个方法,其实这也是封装一个方面的体现,如果上面 代码我们有两个函数,A函数与B函数,在这两个函数最前面有一个需要,就是要进行一个name与number的验证,如果我们把这个验证的功能分别写在A函数与B函数里面,是不是就会这样:
1 //这个是一个A函数
2 public voidA(){3
4 if(name.equals("A")&&number.equals("A")){5 return true;6 }else{7 return false;8 }9
10 System.out.println("这是一个A函数");11 }12
13 //这个是一个B函数
14 public voidB(){15
16 if(name.equals("B")&&number.equals("B")){17 return true;18 }else{19 return false;20 }21
22 System.out.println("这是一个B函数");23 }
这样是不是就会带来两个问题一个是代码的冗余度加大,另一个问题就是降低了代码的可维护性,因为我要修改yanZheng方法,如果它被封装成一个方法,那么在维护的时候,只要在维护这一处就可以了。而如果分别放在A,B两个方法中,那就要维护两个地方。
三:通过上面的描述,我们可以简单的总结出封装的好处
1. 良好的封装能够减少耦合和提高维护性。
2. 可以对成员变量进行更精确的控制。
3. 隐藏信息,实现细节。