回忆
- 方法重写
- 指的是 子类中定义 了跟父类(父代)方法签名一致
- 返回值类型 方法名 参数列表 必须一致
- 修饰符 不能比父类的 权限低
- 用途:
- 子类要完全修改父类的行为
- 子类要扩展父类的行为
- 指的是 子类中定义 了跟父类(父代)方法签名一致
- final
- 修饰的内容不同意义不同
- 修饰类:表示类不能被继承
- 修饰成员方法: 表示方法不能被重写
- 修饰局部变量: 是一个常量
- 修饰成员变量:是一个常量,且不能使用默认值,必须显式赋一次值。
- 多态
- 同一个事物在不同时刻的不同体现
- 父类型 变量名 = 子类型变量;
- 要继承(建立父类和子类的关系)
- 重写
- 成员变量
- 编译看左边,运行看左边
- 成员方法
- 编译看左边,运行看右边
- 静态变量
- 编译看左边,运行看左边
- 静态方法
- 编译看左边,运行看左边
- 所谓的弊端:当我需要访问子类特有的行为时,必须向下转型
- 强转: 子类类型 变量名 =(子类类型)父类变量;
- 当两个类型不具备继承关系时,不能使用强转,就发生编译错误。
- 即使两个类有继承关系,如果它引用的对象不是某个子类,运行时也会发生异常:
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eSAovdN3-1593181447753)(imges/image-20200622093319513.png)]
- 如何确保这个转换可以安全的进行呢?
instanceof
关键字配合if来使用。- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZjXCywR0-1593181447755)(imges/image-20200622093704527.png)]
- 强转: 子类类型 变量名 =(子类类型)父类变量;
- 方法相关特点:
- 当父类型作为方法参数时,调用时可以传递 父类类型的对象或子类类型的对象(多态)。
- 当父类型作为方法返回值时,也可以返回 父类类型的对象或子类类型的对象(多态)。
抽象类
当某个类表示一种抽象的概念的时候,new它没有实际意义。所以会考虑将它设置为抽象类。
标识抽象类的方式也很简单,只需要在 class 关键字前面添加 abstract
修饰符即可。
abstract class ClassA{
//定义了一个抽象类 ClassA
}
其实,Java中还存在一种更细粒度的抽象,称为:抽象方法
。
当父类中的某个方法总是会被子类所重写,那么在父类中实现该方法也是没有实际意义的。此时,应该将该方法声明为抽象方法。
将一个方法声明为抽象方法:
- 在返回值类型前面添加关键字
abstarct
- 去掉大括号(意味着抽象方法没有方法体),注意分号不能丢
其它修饰符 abstract 返回值类型 方法名(参数类型 参数名,....);
注意事项
- 一个抽象类中可以包含所有非抽象的内容
- 一旦一个类中包含了抽象的方法,这个类必须声明为抽象类。
- 如果一个抽象类中包含了抽象方法,其子类的选择
- 子类也可以是抽象类
- 子类可以是具体类,必须实现(重写)父类的抽象方法 ,可以选择性的重写父类的其它成员方法。
- 抽象类照样可以包含构造方法
- 抽象类中的构造方法往往用于数据的存储。
练习:
老师、学生
都是人。都具备姓名、年龄。有差异。
都能吃饭、睡觉。一个学习,一个授课。
你来完善它们的完整的OOP的内容。
思考
- 抽象类一定是父类 ? 是
- 如果一个类没有抽象方法,能否定义成抽象类?可以。
- 又有什么意义呢?不想直接让用户实例化它。
- 你觉得abstract关键字跟哪些你学过的关键字冲突呢?
- private
- final
- static
接口
假设 狗能看门(有陌生人进来,就会叫唤-报警机制)。 现在,出现了智能摄像头(有陌生人进来,就会报警)… 分析,它们具备共同的行为,如何抽象呢?
首先考虑,继承可以吗?
- 技术上可以。
- 道理上说不通。那个父类是个什么玩意?因为继承往往体现的是 is a 的关系。所以,这种情况下,无法生搬硬套将它们归为一类。
此时,接口技术就可以来满足我们的需求。
接口更多的侧重点在于行为的抽象。
万事万物都有行为,都可以用接口来描述。
java语言对接口的支持需要配合关键字 interface
,仍然定义在 .java
文件中。且编译完之后仍会产生.class文件。所以,本质上 接口也是一种特殊类型的 类。
//定义格式
interface 接口名{ //将class关键字替换为 interface 关键字。
}
接口的组成
反编译工具:
- 编译 .java -> .class
- 可以引入一些代码混淆工具
- 反编译 .class -> .java
- 可以包含成员变量,且只能是常量,必须赋值且赋值一次。这些常量都是静态的
int a = 10
public int a = 10
public static int a =10
public static final int a =10
- 不可以包含任何构造方法
- 成员方法: 必须都是抽象方法
- 非静态的方法必须去掉方法体,用分号结束。
- 修饰符的部分:
void m1()
public void m1();
public abstract void m1();
- 静态方法:正常写就ok。
接口的使用
-
接口可以被其他接口继承
-
interface 接口1{ } interface 接口2 extends 接口1{ }
-
-
接口可以被其他类实现
implements
关键字-
interface 接口{ } class 类 implements 接口{ }
-
接口的特点
-
类与类
- 继承关系,只支持单继承,可以多层继承。
- 通过final来阻断
-
类与接口
- 实现关系。既可以单实现,也可以多实现。最复杂的场景就是继承一个类的同时实现某些接口。
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EwXqCazG-1593181447757)(imges/image-20200622143951615.png)]
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZC7eQ1GF-1593181447759)(imges/image-20200622144049491.png)]
-
接口与接口
- 是继承关系。既可以单继承,也可以多继承。
接口和抽象类的区别
- 成员上的区别
- 接口 : 常量、抽象方法、静态方法。
- 抽象类:变量、常量、成员方法、抽象成员方法、静态方法。
- 关系上的区别
- 类与类
- 类与接口
- 接口与接口
- 设计理念上的差别
- 抽象类是被继承的体现。 “is a”的关系,共性的功能
- 接口被现实的体现。“like a”的关系,是一个扩展的功能。
练习体会。
老师、学生。抽象类的实现。
老师中有一部分人要抽烟
Teacher implements XXX //意味着所有老师都要抽烟,不符合题干
XXXTeacher extends Teacher implements XXX //这里
学生也有一部分人要抽烟。
如何来描述这种情况呢?试着改造一下原有的设计。
方法调用中参数和返回值的问题
-
参数类型
- 基本数据类型: 调用时要求什么类型就传递什么类型。或者能自动类型转换
- 普通类:类的对象,或者子类对象。
- 抽象类:一定是子类对象。
- 接口:实现(可以是直接实现,也可以是间接实现)了该接口的对象。
-
返回值类型
-
基本数据类型: 要什么类型返回什么类型。或者能自动类型转换。
-
普通类型: 类的对象,或者子类对象。
-
抽象类:一定是子类对象。
-
接口:实现(可以是直接实现,也可以是间接实现)了该接口的对象。
-
链式编程
比如说有一个对象,在正式使用之前需要设置大量的相关属性。
public class _10Chain {
public static void main(String[] args) {
Condition condition = new Condition();
condition.setC1(1);
condition.setC2(2);
condition.setC3(3);
condition.setC4(4);
//进入下一步的逻辑.....
//链式思想的 “类set方法” 都会原样返回对象本身
Condition condition1 = new Condition()
.C1(1)
.C2(2)
.C3(3)
.C4(4);
}
}
//表示飞行条件
class Condition{
//风速
private int c1;
//湿度
private int c2;
//速度
private int c3;
//能见度
private int c4;
public int getC1() {
return c1;
}
public Condition C1(int c1){
this.c1 = c1;
return this;
}
public void setC1(int c1) {
this.c1 = c1;
}
public int getC2() {
return c2;
}
public Condition C2(int c2){
this.c2 = c2;
return this;
}
public void setC2(int c2) {
this.c2 = c2;
}
public int getC3() {
return c3;
}
public Condition C3(int c3){
this.c3 = c3;
return this;
}
public void setC3(int c3) {
this.c3 = c3;
}
public int getC4() {
return c4;
}
public Condition C4(int c4){
this.c4 = c4;
return this;
}
public void setC4(int c4) {
this.c4 = c4;
}
}
包
包其实就是文件夹。用来存放 .java 文件。目的是为了对Java类/接口…进行分类管理。之所以进行分类管理:
- 相同方面的某些类放在一起,好找。
- 解决类名冲突的问题。
- java要求相同包下面只能包含唯一的类名。
声明语法:
package 包名;
//包名属于标识符。
//规范:
//1. 包名的所有字母全部小写
//2. 一般会采用以下模式来命名:
// 2.1 第一部分域名倒写。 比如百度公司的域名是 baidu.com, 所以,假设你是百度公司的程序员,那么我公司开发的Java程序的顶层包名: com/baidu
// 2.2 第二部分是项目/软件/产品...其它代号。比如我的程序是百度公司的贴吧产品相关的源码。这层包就可以命名为: tieba
// 2.3 对于贴吧产品来说,也会进行进一步的分层,模块层面。比如回复模块,我的包名命名: reply
// 2.4 进一步回复模块内部,从技术上考虑也会分成不同的部分(技术层面,现在很可能无法深入的了解)。常见的内容如下:
entity/model/domain .... 对应数据库的表
dao/impl ..... 对应数据访问层的对象,就是如何操作数据库
service/impl ...... 对应业务逻辑
web/controller ..... 对应界面逻辑
util .... 对应工具类
//总结,以XXX工具类来说,它应该放入包:
com/baidu/tieba/reply/util/XXX.java
//对应的java语法的声明
package com.baidu.tieba.reply.util;
如何被其他类所使用呢?在其它类的.java文件中,访问你的java类。
导入
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cmpo4tAQ-1593181447761)(imges/image-20200622173437194.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u2P98DDH-1593181447763)(imges/image-20200622173806561.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9TfNk1IQ-1593181447764)(imges/image-20200622174237055.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i5pR7pyO-1593181447766)(imges/image-20200622174403734.png)]
静态导入
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PeE9l95J-1593181447767)(imges/image-20200622175301667.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NC71oaFL-1593181447769)(imges/image-20200622175538565.png)]
注意事项
- package 语句必须是程序中的第一条可执行语句(如果前面有注释是可以的)。
- 可以省略。
- 如果出现,只能出现一次。
- import语句必须写在class的前面package的后面
- 可以出现多次
- 如果没有定义package,说明它是 “默认包” 下。
- 非默认包下的类中无法导入 “默认包“ 下的类。反过来是成立的。