大佬给推荐的韩顺平老师的课程 2021年刚刚录的船新版本!
【零基础 快速学Java】韩顺平 零基础30天学会Java
我整理的学习路线与各章节学习笔记戳这里
硬把从另一个讲师那里看了300多集的我拽过来 几十节课一下子爱上这个节奏了!安利!!
具有其他语言基础的盆友只需要把前几章的章节总结简单看一下 然后再去着重看需要学习的章节就可以了!
知识点分的非常清晰! 每章还有总结 这…真的是我理想中的学习资料呐!
学习笔记整理过后放到这里
本专题包括以下几个主要知识点~
本次笔记主要记录 抽象类 、 接口的内容
这两部分是非常重点的作用 同时这两者也是有一些关联的 让我们看看这两个部分的内容吧
先来看一段代码
class Animal{
private String name;
private int age;//属性定义
public Animal(String name, int age){
//含参构造器
super();
this.name = name;
this.age = age;
}
//动物都有eat的行为
public void eat(){
System.out.println("这里是某只动物 但是由于不清楚品种 所以目前不知道要吃啥 eat方法先声明着哈");
}
//上面这种方法的声明并没有啥意义哦!
public abstract void eat();
}
可以看到 这个 eat()
方法就是先声明出来 但是不确定如何实现
总结下
父类Animal中某些方法 需要声明但又不确定如何实现时 可以将其生命为抽象方法 那么这个父类Animal就是抽象类
访问修饰符 abstract 类名{}
访问修饰符 abstract 返回类型 方法名(参数列表);
//没有方法体哦!!
抽象类的价值更多作用是在于设计 设计者设计好抽象类让子类继承并具体实现这个抽象类
抽象类是面试官比较爱问的知识点哦! 框架和设计模式中使用得较多!
public class AbstractDetail01 {
public static void main(String[] args) {
//抽象类A 不能被实例化
//new A();
}
}
abstract class A {
public void hi() {
System.out.println("hi");
}
}
抽象类中可以没有abstract方法哦!
abstract class A {
public void hi() {
System.out.println("hi");
}
}
比如 非抽象方法 构造器 静态属性啥的 都星~
abstract class E {
public abstract void hi();
}
abstract class F extends E {
//这样不行!
}
class G extends E {
@Override
public void hi() {
//这里相等于 G 子类实现了父类 E 的抽象方法
//所谓实现方法,就是有方法体
}
【零基础 快速学Java】韩顺平 零基础30天学会Java_哔哩哔哩_
第四题——
超级好的一个例子哈!
抽象这个work方法 在设计虚拟类的时候就先不用考虑不同的员工对应的work方法内容不同该咋实现了!先定义抽象方法就行!
public class AbstractExercise01 {
public static void main(String[] args) {
//测试
Manager jack = new Manager("jack", 999, 50000);
jack.setBonus(8000);
jack.work();
CommonEmployee tom = new CommonEmployee("tom", 888, 20000);
tom.work();
}
}
abstract public class Employee {
//开始写抽象类Employee
private String name;
private int id;
private double salary;
public Employee(String name, int id, double salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
//将 work 做成一个抽象方法
public abstract void work();
//6个 getter setter方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
public class Manager extends Employee {
//继承抽象类后 要实现所有抽象方法!
private double bonus;
public Manager(String name, int id, double salary) {
super(name, id, salary);
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
@Override
public void work() {
System.out.println("经理 " + getName() + " 工作中...");
}
}
public class CommonEmployee extends Employee{
//继承抽象类后 要实现所有抽象方法!
public CommonEmployee(String name, int id, double salary) {
super(name, id, salary);
}
@Override
public void work() {
System.out.println("普通员工 " + getName() + " 工作中...");
}
}
二刷建议详细走一遍视频 跟着敲一下代码!
这个实践真的非常棒!可以帮助我们强化抽象类的思想!
推荐练习的一个案例 强化抽象类的思想!
抽象类体现的就是一种模板模式的设计 (抽象类作为多个子类的通用模板 )
子类在抽象类的基础上进行扩展、改造 但是子类总体上会保留抽象类的行为方式
1.有多个类 用于完成不同的任务 job
2.要求统计得到各自完成任务的时间
编程实现这个抽象类吧!
template是 模板 的意思~
在这个案例中 我们假设需要给很多很多工作计算工作时间!
其中 计算工作时间的方法 可以写一个统一的方法 calculateTime()
而每一个工作不同的地方
abstract public class Template { //抽象类-模板设计模式
public abstract void job();//抽象方法
public void calculateTime() {//实现方法,调用 job 方法
//得到开始的时间
long start = System.currentTimeMillis();
job(); //复习下动态绑定机制——
//虚拟机调用实例方法job()时,它会基于对象实际的类型(只能在运行时得知)来选择所调用的方法job()的具体内容,这就是动态绑定,是多态的一种。
//在这里就是 根据子类重写的对象 来确定job()的具体内容~
//得的结束的时间
long end = System.currentTimeMillis();
System.out.println("任务执行时间 " + (end - start));
}
}
public class AA extends Template {
//计算任务
//1+....+ 800000
@Override
public void job() {
//实现 Template 的抽象方法 job
//方法内容是 进行80w次循环
//除了实现这个抽象方法 其他的方法都不用写了!方便!!
long num = 0;
for (long i = 1; i <= 800000; i++) {
num += i;
}
}
}
public class BB extends Template{
public void job() {//这里也去重写了 Template 的 job 方法 循环8w次
long num = 0;
for (long i = 1; i <= 80000; i++) {
num *= i;
}
}
}
public class TestTemplate {
public static void main(String[] args) {
AA aa = new AA();
aa.calculateTime(); //这里还是需要有良好的 OOP 基础,尤其是对多态的理解
//我们不需要在AA类中编写具体的计算工作时间的方法
//只需要把AA类中简单的“工作内容”这部分的代码编写好 剩下的用抽象类中的方法即可完成要求!!
//各个类中的代码量大大减少!!
BB bb = new BB();
bb.calculateTime();
}
}
可以看看之前的代码 复用性极差!
public class AA{
public void job() {
//反面教材! : 每个类都去实现 计算工作时间的方法
// 得到开始的时间
long start = System.currentTimeMillis();
long num = 0;
//任务具体内容
//用到了抽象类之后 AA类中只要实现这部分就OK了!
for (long i = 1; i <= 200000; i++) {
num += i;
}
// 得的结束的时间
long end = System.currentTimeMillis();
// 相减即可得到类中方法执行时间
System.out.println("AA 执行时间 " + (end - start));
}
}
上面的抽象类这么一看真是香得一批啊!
体现了模板设计模式——对代码的简洁性和复用性有很大的帮助哦!
这里一定要好好看 认真理解哦!
下面来学习接口的内容
https://www.bilibili.com/video/BV1fh411y7R8?p=403&spm_id_from=pageDriver
老韩举了一个很形象的例子
电脑的USB 分别连接 手机和照相机等
分别要完成这些代码 即可完成一次接口的应用
经过这个形象的例子快速入门之后 来看看接口到底是个啥
接口就是给出一些没有实现的方法 并将它们封装到一起 某个类(即前面提到的手机类、照相机类)要使用这些方法的时候 根据具体情况在类中把这些方法写出来就行~
各自的语法如下:
interface 接口名{
//属性
//抽象方法
}
class 使用接口的类 implements 接口{
自己的属性与方法;
必须实现的接口的抽象方法;
}
抽象类中的方法可以有方法体!(当然了抽象方法也是不可以有方法体的~)但是接口里的所有方法都没有方法体【jdk7.0】
注意~ jdk8.0之后 接口类可以有静态方法、默认方法
也就是接口中可以有方法的具体实现
接口的概念并不难 难的是“要清楚什么时候使用接口”
之前我们在抽象类定义抽象方法还得要
public abstract void aa();
而接口中默认所有方法都是public方法 且 是抽象的了(不知道jdk8.0还是不是这样哈 在jdk7.0之前都是这样亚子的!)
void aa();//默认是public 抽象 的方法
注意是所有方法哦!都要实现!不然会报错
如果是个抽象类就不用像3.1中一样实现所有方法了
按理说 Java是不支持类的多重继承的 一个类只能继承一个类
但是!如果搬到接口这里 一个类可以继承多个接口 这也算是某种程度上达到了多重继承!
int a = 1;
public static final int a = 1;
//在接口中这两个定义属性a的方法是等价的
//(戏真多啊...)
复习下final修饰符的作用——修饰类中的某个不希望被修改的属性值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vhmzrcjp-1627996818143)(03 面向对象高级.assets/image-20210803193642404.png)]
接口名.属性名;
interface A extends B,C{
//B C都是接口 嗯!
}
这点和类的修饰符是一样的!普通的类也只是用public和默认修饰符 因为用protected和private来修饰也没啥意义不是么~
interface A{}
public interface A{}
https://www.bilibili.com/video/BV1fh411y7R8?p=408
重头戏来了!
我们来探究下接口和继承解决问题的不同
另外还有很重要的一点!接口比继承更加灵活!!
继承满足 is-a
的关系 即继承了B的A类一定要是B才行!!
人不能继承Dog类 不满足is-a关系 而柯基、吉娃娃就可以~
接口只需要满足 like-a
的关系 实现接口是对Java单继承机制的一个重要补充!它让程序设计更加灵活!
看下面这个例子 小猴子可以使用
Fishable
Birdable
的接口
//猴子
class Monkey {
private String name;
public Monkey(String name) {
this.name = name;
}
public void climbing() {
System.out.println(name + " 会爬树...");
}
public String getName() {
return name;
}
}
//接口
interface Fishable {
void swimming();
}
interface Birdable {
void flying();
}
//继承
//小结: 当子类继承了父类,就自动的拥有父类的功能
// 如果子类需要扩展功能,可以通过实现接口的方式扩展.
// 可以理解 实现接口 是 对 java 单继承机制的一种补充.
class LittleMonkey extends Monkey implements Fishable,Birdable {
public LittleMonkey(String name) {
super(name);
}
@Override
public void swimming() {
System.out.println(getName() + " 通过学习,可以像鱼儿一样游泳...");
}
@Override
public void flying() {
System.out.println(getName() + " 通过学习,可以像鸟儿一样飞翔...");
}
}
可以看到上面的小猴子类是可以继承猴子类的同时使用接口Fishable
Birdable
测试一下
public class ExtendsVsInterface {
public static void main(String[] args) {
LittleMonkey wuKong = new LittleMonkey("悟空");
wuKong.climbing();
wuKong.swimming();
wuKong.flying();
}
}
接口是可以体现出多态参数的!
前面有说过这个~
在前面的Usb接口
案例中 我们使用——
如图所示的work方法时
这说明接口体现了多态参数!(形参既可以接收手机对象 又可以接收相机对象)
学术一点说就是:接口引用
usbInterface
可以指向接口的类的对象camera
、phone
等
interface Usb{
void work();
}
public class InterfacePolyArr {
public static void main(String[] args) {
//多态数组 -> 接口类型数组
Usb[] usbs = new Usb[2];
usbs[0] = new Phone_();
usbs[1] = new Camera_();
/*
给 Usb 数组中,存放 Phone 和 相机对象,Phone 类还有一个特有的方法 call(),
请遍历 Usb 数组,如果是 Phone 对象,除了调用 Usb 接口定义的方法外,
还需要调用 Phone 特有方法 call
*/
for(int i = 0; i < usbs.length; i++) {
usbs[i].work();//动态绑定.. //和前面一样,我们仍然需要进行类型的向下转型
if(usbs[i] instanceof Phone_) {//判断他的运行类型是 Phone_
((Phone_) usbs[i]).call();
}
}
}
啥是接口的多态传递?
上代码
/**
* 演示多态传递现象
*/
public class InterfacePolyPass {
public static void main(String[] args) {
//接口类型的变量可以指向,实现了该接口的类的对象实例
IG ig = new Teacher();
//如果 IG 继承了 IH 接口,而 Teacher 类实现了 IG 接口
//那么,实际上就相当于 Teacher 类也实现了 IH 接口.
//这就是所谓的 接口多态传递现象.
IH ih = new Teacher();
}
}
interface IH {
void hi();
}
interface IG extends IH{}
class Teacher implements IG {
@Override
public void hi() {
}
}
https://www.bilibili.com/video/BV1fh411y7R8?p=412
下面为后面要学习的内容做一个预告~
内部类——程序员技术水平的一个分水岭!
学好内部类 我们对面向对象的认识可以再上一个台阶!!
下面的章节中我们将针对内部类进行学习