第一章 接口
1.1 接口的概念
1.概念:
对外暴露的规则/规范/标准,只要符合该规则/规范/标准的东西都可以使用
2.接口,是Java语言中一种引用类型,编译后也有对应的class文件,是方法的汇总3.作用: 实现对类的功能的扩展,解决java中类的单继承的局限性
1.2 接口中可以定义的内容
1.抽象方法【jdk7及以前】: public abstract 返回值类型 方法名称(参数列表...); 没有方法体{}
2.默认方法【jdk8及以后】: public default 返回值类型 方法名称(参数列表...){...} 有方法体{}
3.静态方法【jdk8及以后】: public static 返回值类型 方法名称(参数列表...){...} 有方法体{}
4.常量【jdk7及以前】:public static final 数据类型 变量名称 = 数据值; 不可以修改其值
注意:
接口在设计之初只是为了制定一套规则/规范/标准,所以接口设计之初内部只能定义抽象方法
1.3 接口的定义格式
类的定义格式
修饰符 class 类名 {
//成员变量
//常量
//成员方法
//构造方法
//静态方法
}
接口的定义格式
public interface 接口名称 {
//常量
//抽象方法
//默认方法
//静态方法
}
1.4 接口中抽象方法的定义格式和使用
1.接口中抽象方法的定义格式
public abstract 返回值类型 方法名称(形式参数列表...);
注意:
(1)和以前定义方法格式相同,但是需要去掉{},添加abstract
(2)返回值类型和参数列表根据需求确定
(3)接口中抽象方法,有默认修饰符public abstract,不写也有
抽象类中抽象方法必须写public abstract,不能省略
2.接口中抽象方法的使用
(1)不能直接创建接口的对象
(2)定义实现类 实现 接口 关键字 implements
格式:
public class 类名 implements 接口A,接口B {
//覆盖重写接口中的所有的抽象方法
}
(3)实现类中覆盖重写接口中的所有的抽象方法
去掉abstract关键字,添加{}
快捷键: ctrl + i
(4)创建实现类对象
(5)使用实现类对象调用方法//定义接口
public interface MyInter01 {
//抽象方法
public abstract void method();
void show();
}
//定义实现类MyInter01Impl 实现 接口MyInter01
public class MyInter01Impl implements MyInter01{
@Override
public void method() {
System.out.println("MyInter01Impl...method...");
}@Override
public void show() {
System.out.println("MyInter01Impl...show...");
}
}
//接口中抽象方法的定义格式和使用
public class Demo01Interface {
public static void main(String[] args) {
//错误: 接口不能直接new对象
//MyInter01 mi01 = new MyInter01();//创建实现类对象
MyInter01Impl mi01 = new MyInter01Impl();//使用实现类对象调用方法
mi01.method();
mi01.show();}
}
1.5 接口中默认方法的定义格式和使用
接口中默认方法的定义格式和使用
问题:
定义接口后,有很多实现类在使用接口,如果对接口功能升级添加了新的抽象方法
导致所有的实现类必须修改代码,太麻烦解决方案: 默认方法
默认方法的定义格式:
public default 返回值类型 方法名称(形式参数列表...){
//方法体;
}默认方法的使用:
1.不能使用接口名称调用默认方法
2.不能使用实现类名称调用默认方法
3.只能使用实现类对象调用默认方法注意:
1.接口中的默认方法,不强制要求实现类进行覆盖重写
2.但是实现类可以根据需求,选择性的覆盖重写接口中的默认方法
3.如果实现类覆盖重写接口中的默认方法,必须去掉default关键字
1.6 接口中的静态方法的定义和使用
1.定义格式
public static 返回值类型 方法名称(形式参数列表...) {
方法体;
}2.使用格式
(1)只能使用接口名称调用接口中的静态方法
(2)不能使用实现类名称调用接口中的静态方法
(3)不能使用实现类对象调用接口中的静态方法3.注意:
(1)接口中的静态方法,属于接口本身,与实现类无关,在实现类中不存在覆盖重写
(2)类中的静态方法,属于类本身,与接口无关,与对象无关
(3)类中的静态方法:
名直接调用 ---推荐使用
对象直接调用 ---不推荐使用总结: 静态的内容要么用接口名称调用,要么用类名称调用
1.7 接口中成员变量的使用
接口中成员变量的使用
接口中定义的变量,都是常量(值不可以改变)
默认修饰符public static final 不写也有
接口中常量默认值认为是无效的必须显式赋值
接口中的常量的使用: 接口名称.常量名称
建议: 接口中常量的命名全部使用大写字母,单词之间用_分隔
1.8 接口的多实现
接口的多实现
在继承体系中,一个类只能继承一个父类【类的单继承: 亲爹只能有一个】。
对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现【类实现接口的多实现: 干爹可以有多个】。并且,一个类能继承一个父类,同时实现多个接口。
一个类能继承一个父类,同时实现多个接口格式:
public class 子类名 extends 父类名 implements 接口名A,接口名B {
覆盖重写抽象父类和接口中的所有的抽象方法
}注意:
子类必须重写父类和接口中的所有抽象方法,只要有一个抽象方法没有被重写,该子类必须定义为抽象类,看AbstractZi05类
1.9 多个接口中重名的抽象方法
多个接口中重名的抽象方法
实现类: 只需要覆盖重写一次
1.10 多个接口中重名的默认方法
多个接口中重名的默认方法
实现类,必须覆盖重写一次,而且要去掉default关键字
1.11 多个接口中重名的静态方法
多个接口中重名的静态方法
接口中静态方法属于接口本身,和实现类无关
只能使用接口名称调用多个接口中重名的静态方法
接口中的静态方法属于接口本身,与实现类无关
只能用接口名称调用
所以多个接口中重名的静态方法之间互不影响,
直接使用对应的接口名调用接口
1.12 抽象类和接口的区别
抽象类和接口的区别
1.内容上的区别?
抽象类: 成员变量,常量,构造方法,成员方法,静态方法
接口: 常量,默认方法,静态方法2.本质上的区别:
抽象类: 本质是一个类,就是对某种事物的描述
整个继承体系中的共性内容接口: 是用来制定规则/规范/标准的,只要符合规则/规范/标准都可以用
扩展继承体系中的类的功能的
1.14 没有抽象方法的抽象类存在意义
抽象类中可以没有抽象方法,存在的意义是什么?
适配器设计模式
1.接口中定义了相当多的抽象方法
2.实现类,想实现接口,但是只会用到接口中的某个/某几个方法
如果实现类 实现接口的 话 ,必然覆盖重写所有的抽象方法 相当麻烦3.解决方案:
根据接口创建一个实现类,所有被重写后的方法的{}中没有任何代码
对接口进行空实现,因为实现类中的所有方法{}中没有代码,
所以创建实现类的对象调用方法,没有意义,把该实现类定义为抽象类,
用户创建抽象类的子类,根据需求重写方法
第二章 多态
2.1 生活中的多态
面向对象的三大特征: 封装,继承,多态
封装: 提高代码的安全性
继承: 提高代码的复用性
多态: 提高代码的扩展性
多态的概念:同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。
简单的理解: 同一个事物,表现出来不同的形态
举个栗子:
比如说你自己
在学校中: 是一个学生
在餐馆中: 是一个顾客
在公司中: 是一个员工
在你家里: 是妻子/丈夫
回老家: 是一个孩子
比如说H2O:
在常温下: 是液体
在高温下: 是水蒸气
在低温下: 是固体冰
2.2 多态中的代码体现
多态中的代码体现
1.概念:
同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。
java中的多态: 指的是对象具备多态性
2.举例:
假设学生Student类是人Person类的子类
学生 是 一个学生
//不是多态 左侧是Student类型,右侧是Student对象,左右一致
Student stu = new Student();学生 是 一个人
//是多态 左侧是Person类型,右侧是Student对象,左右不一致,左边是父类,右边是子类对象
Person p = new Student();3.多态的前提:
(1)必须要有继承或者接口实现
(2)必须要有父类引用指向子类对象(父类类型的变量保存子类对象的地址值)
(3)必须要有方法的覆盖重写,否则将失去多态的意义
4.多态的本质
(1)就是把子类对象当成父类类型使用
父类引用指向子类对象(父类类型的变量保存子类对象的地址值)(2)多态的方式调用方法,方法跟着对象走
2.3 多态的好处和弊端
多态的好处和弊端
不使用多态:
好处: 可以调用子类的特有行为
弊端: 扩展性极差
使用多态:
好处: 扩展性强
弊端: 不可以调用子类的特有行为多态的好处:
可以使用父类/接口,作为方法的参数,提高方法的扩展性
问题:
下面分别是有Animal的子类Dog和Cat作为方法参数,定义了两个方法
Animal的子类可以有任意多个,这样定义的方法也就会有任意多个
每创建一个子类,就得再添加一个方法,太麻烦解决方案:
所有的子类对象,都可以当做父类类型使用
所以可以使用父类类型作为方法的参数
类作为方法的参数:
调用方法时,传递的是该类的对象或者是该类的子类对象类的数据体现形式是对象
抽象类的数据体现形式是子类对象
接口的数据体现形式是实现类对象
暴露新的问题: 方法内部不能直接调用子类的特有行为了
2.5 多态中的向上向下转型
多态中的向上转型
多态的本质(父类引用指向子类对象): 就是向上转型
类似于 基本类型的自动类型转换
取值范围小的数据或者变量可以直接赋值给取值范围大的变量int a = 100;//int: 占4个字节
double d = a;//double: 占8个字节不需要进行特殊的处理
多态中的向下转型
类似于 基本类型的强制类型转换
取值范围大的数据或者变量不可以直接赋值给取值范围小的变量double d2 = 100;//double: 占8个字节
int c = (int)d2;//int: 占4个字节强制类型转换:
转后类型 对象名称 = (转后类型)转前的对象或者变量名称;
注意:多态的向下转型(强制类型转换)存在安全隐患
如果转换前的类型和转换后的类型不一致,就会报出类型转换异常(ClassCastException)
2.6 instanceof关键字
强制类型转换(向下转型)存在安全隐患:
如果转后类型和创建对象的具体类型不一致,报出类型转换异常 ClassCastException
如何解决呢?
如果变量a指向的是Dog类型,强制转换成Dog对象
如果变量a指向的是Cat类型,强制转换成Cat对象
如何判断变量a指向的到底是哪种类型的对象呢?使用instanceof关键字
使用格式:
boolean result = 对象名 instanceof 类名
如果对象名称中保存的是该类的对象,返回true。
如果对象名称中保存的不是该类的对象,返回false。