面向对象进阶第二天
权限修饰符
作用:约束成员变量,构造器,方法等的访问范围
自己定义成员(方法,成员变量,构造器等)一般需要满足如下要求:
-
成员变量一般私有。
-
方法一般公开。
-
如果该成员只希望本类访问,使用private修饰。
-
如果该成员只希望本类,同一个包下的其他类和不同包下的子类访问,使用protected修饰。
-
final关键字
final最终的意思
-
final修饰类:类不能被继承。工具类可以用final修饰。
-
final修饰方法:该方法被称为最终方法,特点是不能被重写了。 模板方法可以用final
-
final修饰变量:总规则:有且仅能被赋值一次。
注意:final修饰基本数据类型的变量,其存储的数据不能改变。final修饰引用类型的变量,其存储的地址不能改变,但是指向的对象内容可以改变。
常量
-
是什么?
-
public static final 修饰的成员变量,必须有初始化值,执行过程中值不能改变。
-
-
作用:做系统的配置信息,做信息标志和分类
-
规范:名称全部大写,多个单词用下划线连接
-
常量在编译阶段会进行“宏替换”:把使用常量的地方全部替换成真实的字面量
-
// 请在下方声名一个常量VERSION_NAME,值为"v1.0.0",用于记录系统的版本名称。 public static final String VERSION_NAME = "v1.0.0";
抽象类
抽象类是什么?abstract修饰的类
抽象方法是什么?abstract修饰的方法,不能写方法体。
作用:
-
被子类继承。
-
如果父类知道子类一定要做这件事,但是每个子类做的不一样,父类可以声明抽象方法,交给子类重写来实现。这个类就是抽象类了。
抽象类的特点:
-
类有的成员(成员变量、方法、构造器)抽象类都具备
-
抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
-
一个类继承了抽象类必须重写完抽象类的全部抽象方法,否则这个类也必须定义成抽象类。
-
不能用abstract修饰变量、代码块、构造器。
-
最重要的特征:得到了抽象方法,失去了创建对象的能力(有得有失)
模板方法设计模式
-
模板方法模式解决了什么问题?
-
提高了代码的复用性
-
模板方法已经定义了通用结构,模板方法不能确定的部分定义成抽象方法,交给子类实现,因此,使用者只需要关心自己需要实现的功能即可。
-
模板方法模式中的通用结构建议加上final修饰,好处是可以防止子类重写模板方法。
-
多态
面向对象的三大特征之一:封装、继承、多态
含义? 指的是对象有多种形态
-
人类型的对象:学生对象
-
人类型的对象:老师对象
-
人类型的对象:丈夫对象
语法形式:
-
父类类型 变量名称 = new 子类构造器;
Animal a = new Cat();
-
接口 变量名称 = new 实现类构造器;
多态的调用方式
-
对于方法的调用:编译看左边,运行看右边
Animal a = new Cat();
a.run(); -
对于变量的调用
-
编译看左边,运行也看左边(注意)
-
-
多态更多用在行为多态
多态的使用前提
1、必须继承、实现
2、父类类型的变量指向子类类型的对象
Animal a = new Cat();
3、存在方法重写
Animal a = new Cat();
a.run();
多态的优势
-
a、多态可以实现解耦合
Animal a = new Dog();
a.run(); -
b、多态下,父类类型作为方法的入参,可以接收一切子类对象,这样更利于方法的扩展和便利性。
-
注意存在的问题:
-
多态下不能直接访问子类独有功能
Animal a = new Dog();
a.lookDoor();
-
多态下类型转换问题
-
自动类型转换
-
从子类到父类
Animal a = new Dog();
-
强制类型转换
-
从父类到子类
-
Animal a = new Dog();
-
必须强制类型转换,否则报错的
-
Dog d = (Dog) a;
-
注意:
-
Java规定,有继承/实现关系的类就可以强制转换,编译阶段不会报错。但是运行时可能出现类型转换异常,ClassCastException。
Animal a = new Cat();
Dog d = (Dog)a; -
编译不出错。运行时出现类型转换异常。
-
-
Java建议在进行强制转换之前先通过instanceof判断真实数据类型,再强转
Animal a = new Cat();
if(a instanceof Cat) {
Cat c = (Cat)a;
} -
强制类型转换解决了什么问题?
-
可以调用子类的独有功能了
-
接口
接口概定义与特点
-
Java提供了一个关键字interface,用这个关键字我们可以定义出一个特殊的结构:接口。
public interface 接口名 {
// 成员变量(常量)
// 成员方法(抽象方法)
}JDK8之前接口中只能是常量和抽象方法,没有其他成分了。
接口本质上是一种规范,约束实现接口的类必须具备某种能力。
-
注意:接口不能创建对象;接口是用来被类实现(implements)的,实现接口的类称为实现类。
修饰符 class 实现类 implements 接口1, 接口2, 接口3 , ... {
} -
一个类可以实现一个或多个接口,实现类实现多个接口,必须重写完全部接口中的全部抽象方法,否则实现类需要定义成抽象类。
接口与接口的关系:多继承
-
一个接口可以同时继承多个接口
注意:实现子接口名的类必须实现后面所有接口中的所有抽象方法。
-
接口多继承的作用
-
规范合并,整合多个接口为同一个接口,便于子类实现。
-
继承抽象类的同时实现多个接口
-
类和类的关系
-
单继承
-
-
类和接口的关系
-
多实现
-
-
因此,我们可以在继承类的同时,实现1个或多个接口,语法如下:
修饰符 class 实现类 extends 基类名 implements 接口1, 接口2, 接口3 , ... {
}
使用接口的好处
-
弥补了类单继承的不足,一个类在单继承的同时还可以实现多个接口。
-
让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现(多态思想)。
JDK8开始接口新增的方法
-
默认方法
-
类似之前写的普通实例方法:必须用default修饰
-
默认会public修饰。需要用接口的实现类的对象来调用
default void defaultMethod() {
System.out.println("接口中的默认方法");
}
-
-
静态方法
-
默认会public修饰,必须static修饰。
-
注意:接口的静态方法必须用本身的接口名来调用。
static void staticMethod() {
System.out.println("接口中的静态方法");
}
-
-
私有方法
-
必须使用private修饰,从JDK1.9才开始有的。
-
根据是否有static关键字修饰,私有方法可以分为非静态私有方法和静态私有方法。
-
非静态私有方法只能在本类中被其他的默认方法或者私有方法访问。
-
静态私有方法还能在本类的其他静态方法中访问。
private void privateMethod() {
System.out.println("接口中的私有方法");
}
-
使用接口的注意事项
-
接口不能创建对象
-
一个类实现多个接口,多个接口的规范不能冲突
-
一个类实现多个接口,多个接口中有同样的静态方法不冲突。
-
一个类继承了父类,同时又实现了接口,父类中和接口中有同名方法,默认用父类的。
-
一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
-
一个接口继承多个接口,是没有问题的,如果多个接口中存在规范冲突则不能多继承。