面试的时候经常被问到面向对象的三大基本特征是什么,一般都能回答出来:封装、继承、多态;但很多人并没有完全理解其中的含义。
一、封装
封装(Encapsulation)是面向对象方法的重要原则,就是把对象的属性和操作(或服务)结合为一个独立的整体,并尽可能隐藏对象的内部实现细节,只保留一些对外接口使之与外部发生联系。系统的其他对象只能通过包裹在数据外面的已经授权的操作来与这个封装的对象进行交流和交互。
封装的特点:
- 隐藏内部程序实现的细节
- 良好的封装能够减少代码之间的耦合度
- 外部成员无法修改已封装好的程序代码
- 可以对成员进行更精确的控制
- 类内部的结构可以自由修改
- 方便数据检查,有利于保护对象信息的完整性,同时也提高程序的安全性
使用private修饰符,表示最小的访问权限。对成员变量的访问,统一提供setXXX,getXXX方法。看下面的例子:
public class User {
private Integer id;
private String username;
private String password;
//用户身份标识(1-申请者,2-审核者)
private Integer type;
private Integer delete_flag;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public Integer getDelete_flag() {
return delete_flag;
}
public void setDelete_flag(Integer delete_flag) {
this.delete_flag = delete_flag;
}
}
对于上面的一个实体对象,大家应该都已经很熟悉了。将对象中的成员变量进行私有化,外部程序是无法访问的。但是我们对外提供了访问的方式,就是set和get方法。而对于这样一个实体对象,外部程序只有赋值和获取值的权限,是无法对内部进行修改,因此我们还可以在内部做一些逻辑判断等来完成我们业务上的需要。
二、继承2.1 什么是继承继承就是使用已存在的类作为基础创建新类的行为,就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为。当然,如果在父类中拥有私有属性(private修饰),则子类是不能被继承的,通过使用继承我们能够非常方便地复用以前的代码,能够大大的提高开发的效率。
2.2 继承的特点只支持单继承,即一个子类只允许有一个父类,但是可以实现多级继承,即子类拥有唯一的父类,而父类还可以再继承。
子类可以拥有父类的非private的属性和方法。
子类可以拥有自己的属性和方法。
子类可以重写覆盖父类的方法。
3.3 构造器、protected关键字、向上转型3.3.1 构造器
我们知道子类可以继承父类的非private属性和方法,另外子类继承不了父类的构造器。对于构造器而言,它只能够被调用,而不能被继承。 调用父类的构造方法我们使用super()即可
继承关系中,父子类构造方法的访问特点:
1,子类会默认调用父类的构造器在,子类构造方法中有一个默认隐含的super();调用,因此一定是先调用父类构造方法,再调用子类构造方法。不过这个默认条件必须是父类有默认构造器。如果父类没有默认构造器,我们就要必须显示的使用super()来调用父类构造器,否则编译器会报错:无法找到符合父类形式的构造器
2,子类构造可以通过super();调用父类的重载构造。
3,用super();调用父类构造方法,必须在子类构造方法中的第一行并且只能调用一次。
3.3.2 protected关键字
对于封装而言,private修饰符是最好的选择,但有时候我们可能有这样的需求:将某些事物尽可能地隐藏,只允许子类的成员来访问它们。这个时候就需要使用到protected。
对于protected而言,对于任何继承此类的子类或者其他任何位于同一个包的类而言,它是可以访问的。
3.3.3 向上转型
将子类转换成父类,在继承关系上面是向上移动的,所以一般称之为向上转型。如:小轿车是继承于车,我们可以说小轿车是车,或者说小轿车是车的一种,这样将小轿车看做车就是向上转型。
3.3.4 继承的优点
1、代码复用
2、提高代码的可扩展性
3、用于实现多态
3.3.5 继承的缺点
1、父类变,子类就必须变。
2、继承破坏了封装,对于父类而言,它的实现细节对于子类来说都是透明的。
3、继承是一种强耦合关系。
三、多态3.1,什么是多态多态是同一个行为具有多个不同表现形式或形态的能力。即程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定。
指向子类的父类引用只能访问父类中拥有的方法和属性,而对于子类中存在而父类中不存在的方法,该引用是不能调用的。若子类重写了父类中的某些方法,在调用方法的时候,必定是使用子类中定义的这些方法(动态连接、动态调用)。
3.2多态的特点1、消除类型之间的耦合关系,实现低耦合。
2、灵活性。
3、可扩展性。
4、可替换性。
3.3多态的条件继承:在多态中必须存在有继承关系的子类和父类。
重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。
向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备调用父类和子类的方法。
3.4实现形式在Java中有两种形式可以实现多态:继承和接口。