前言

b站java课程学习笔记整理。

b站视频: 黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程

169. 多态

指的是同一个对象在不同情况下表现出来的不同形态。

我们可以说Kitty是猫的一种,也可以说Kitty是动物的一种。

多态的前提和实现

  • 有继承/实现关系
  • 有方法的重写
  • 有父类引用指向子类的对象( 动物 animal = new 猫()
1
2
3
4
5
6
7
8
package 多态;

public class Animal {
public void eat(){
System.out.println("动物吃东西");
}
}

1
2
3
4
5
6
7
8
9
package 多态;

public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}

1
2
3
4
5
6
7
8
9
package 多态;

public class test {
public static void main(String[] args) {
Animal A = new Cat();
A.eat();
}
}

总结: 多态就是父类 对象=new 子类;

170. 多态中的成员访问特点

  • 通过多态的形式访问成员变量,编译和运行要看左边。
  • 通过多态的形式访问成员方法,编译看左边(父类中要有这个方法),运行看右边(运行的是子类中重写的方法)。

171. 多态的好处和弊端

  • 好处:多态可以提高程序的拓展性,定义方法时,使用父类定义,具体执行时使用子类的重写方法执行。

  • 弊端:多态不能调用子类特有的方法。

  • 总结: 多态说白了就是调用父类旗下的很多子类时,一个一个添加太麻烦了,可以直接整合调用父类。

代码:

1
2
3
4
5
6
7
8
package 多态;

public class Animal {
public void eat(){
System.out.println("动物吃东西");
}
}

1
2
3
4
5
6
7
8
9
package 多态;

public class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
package 多态;

public class Dog extends Animal{
@Override
public void eat(){
System.out.println("狗吃肉");
}
public void security(){
System.out.println("狗能看门");
}
}

1
2
3
4
5
6
7
8
package 多态;

public class AnimalOperator {
public void operate(Animal a){
a.eat();
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package 多态;

public class test {
public static void main(String[] args) {
Cat c = new Cat();
c.eat();
Dog d = new Dog();
d.eat();

AnimalOperator ao = new AnimalOperator();
ao.operate(c);
ao.operate(d);

// ao.security(d); 无法调用父类没有的,子类特有功能。

}
}

172. 多态中的转型

转型可以实现使用子类中的特有功能。转型分为向上转型(父类引用指向子类对象)和向下转型(父类引用强转为子类对象)。

代码:

1
2
3
4
5
6
7
8
package 多态强转;

public class Animal {
public void eat(){
System.out.println("动物吃东西");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
package 多态强转;

public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
public void play(){
System.out.println("猫玩玩具");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package 多态强转;

public class test {
public static void main(String[] args) {
// 向上转型
Animal a = new Cat();
a.eat();
// 不可以 a.play(); 因为这是猫类特有。


// 向下转型
Cat c = (Cat)a;
c.eat();
c.play();

}
}

173. 多态转型的内存图

多态转型内存一
多态转型内存二
多态转型内存三
多态转型内存四
多态转型内存五

关键就是向下转型时要做一步判断。

174. 猫和狗

案例:猫和狗,需求使用多态的思想实现猫和狗。

  1. 定义动物类,包括成员变量(名字,年龄)、成员方法(getset,吃饭())、构造方法(无参、带参)。
  2. 定义猫类,包括成员方法(重写吃饭())、构造方法(无参、带参)。
  3. 定义狗类,包括成员方法(重写吃饭())、构造方法(无参、带参)。
  4. 定义测试类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package 猫与狗多态;

public class Animal {
private String name;
private String age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAge() {
return age;
}

public void setAge(String age) {
this.age = age;
}

public Animal() {
}

public Animal(String name, String age) {
this.name = name;
this.age = age;
}

public void eat(){
System.out.println("动物吃饭");
}

public void show() {
System.out.println(name + "," + age);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package 猫与狗多态;

public class Cat extends Animal{
public Cat(){}

public Cat(String name, String age){
super(name, age);
}


@Override
public void eat(){
System.out.println("猫吃鱼");
}

public void play(){
System.out.println("猫玩玩具");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package 猫与狗多态;

public class Dog extends Animal{
public Dog(){}

public Dog(String name, String age){
super(name, age);
}


@Override
public void eat(){
System.out.println("狗吃肉");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package 猫与狗多态;

public class Test {
public static void main(String[] args) {
Animal a = new Cat();
a.setAge("21");
a.setName("加菲");
a.show(); //先看cat,发现没有show,就去父类中继承了show。
a.eat();

System.out.println("----------------------------");

Animal b = new Cat("加菲", "10");
b.show();
b.eat();
Cat c = (Cat) b;
c.play();

System.out.println("----------------------------");

Animal d = new Dog("加菲", "10");
d.show();
d.eat();


}
}

总结:继承版猫与狗时提取共性,多态版猫和狗是对一个大类的重写整合。

175. 抽象类

动物不应该作为一个可以被创建对象的类!因为动物就是一个抽象的概念!

一个没有方法体的方法被定义为抽象方法,类被定义为抽象类。

176. 抽象类特点

  1. 抽象类和抽象方法要用abstract关键字来修饰。
  2. 抽象类里是可以有非抽象方法的。但是也可以没有抽象方法(但是没什么意义)。
  3. 类里有抽象方法,类一定是抽象类。
  4. 抽象类无法常规创建对象。抽象类会参照多态的方式创建对象。即先定义一个类继承,然后正常重写方法。
  5. 抽象类的子类要么重写继承所有的抽象方法,要么定义为抽象子类。

177. 抽象类的成员特点

  • 抽象类可以有成员变量(变量或者常量)和非抽象成员方法。

  • 抽象类可以有构造方法(用于多态时子类访问父类时初始化),这个构造方法不是创建对象用的。

178. 猫与狗(抽象类版)

  1. 定义动物类,姓名年龄,无参带参构造,getset方法,抽象eat()方法。
  2. 定义Cat类,继承,无参带参,重写吃饭
  3. 定义Dog类,继承,无参带参,重写吃饭
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package 猫和狗抽象类;

public abstract class Animal {
private String name;
private String age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAge() {
return age;
}

public void setAge(String age) {
this.age = age;
}

public Animal() {
}

;

public Animal(String name, String age) {
this.age = age;
this.name = name;
}

;

public abstract void eat();

public void show() {
System.out.println(name + "," + age);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package 猫和狗抽象类;

public class Cat extends Animal {
public Cat() {
}

public Cat(String name, String age) {
super(name, age);
}

@Override
public void eat() {
System.out.println("猫吃鱼");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package 猫和狗抽象类;

public class Dog extends Animal {
public Dog() {
}

public Dog(String name, String age) {
super(name, age);
}

@Override
public void eat() {
System.out.println("狗吃肉");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package 猫和狗抽象类;

public class test {
public static void main(String[] args) {
Animal a = new Cat();
a.setAge("11");
a.setName("Kitty");
a.eat();
a.show();


Animal b = new Dog("Dogge","19");
b.eat();
b.show();
}
}

总结:就是在猫和狗多态版的基础上,去除了Animal可以实体化的特性,将Animal变成了一个抽象的“定义”。

179. 接口

接口是一种公共的规范标准。只要符合标准,大家都可以用。Java中的接口更多的体现在对行为的抽象。

180. 接口的特点

  1. 接口关键字用interface修饰。
  2. 类实现接口用implements表示。
  3. 接口不能实例化,要参照多态的方式使用子类实例化。
  4. 多态的形式:具体类多态,抽象类多态接口类多态
  5. 接口的实现类:要么重写抽象方法,要么是抽象类。

181. 接口的成员特点

  • 接口中的成员变量默认被public static final修饰。所以接口中默认都是常量。
  • 接口里没有构造方法(所有的子类默认访问的都是object无参构造)
  • 接口里不能有非抽象成员方法。
  • 在接口里的方法默认带了public abstract前缀。

182. 猫和狗接口版

案例:对猫和狗训练,实现跳高功能。

  1. 定义接口,跳高。
  2. 定义动物类,姓名年龄,无参带参构造,getset方法,抽象eat()方法。
  3. 定义Cat类,继承,无参带参,重写吃饭,跳高
  4. 定义Dog类,继承,无参带参,重写吃饭,跳高
    代码只写了个猫的,以猫为例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package 猫和狗接口;

public abstract class Animal {
private String name;
private String age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAge() {
return age;
}

public void setAge(String age) {
this.age = age;
}

public Animal(String name, String age) {
this.name = name;
this.age = age;
}

public Animal() {

}

public abstract void eat();

public void show() {
System.out.println(name + "," + age);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package 猫和狗接口;

public class Cat extends Animal implements Jumpping{
public Cat(){}
public Cat(String name,String age){
super(name, age);
};


@Override
public void eat() {
System.out.println("猫吃鱼");
}

@Override
public void jump() {
System.out.println("猫跳高");
}
}

1
2
3
4
5
6
package 猫和狗接口;

public interface Jumpping {
public abstract void jump();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package 猫和狗接口;

public class test {
public static void main(String[] args) {
// 动物的只能调动物方法
Animal a = new Cat("Kitty","23");
a.show();
a.eat();
// 因为Cat类里面有接口类,所以要想实现只能强转。
((Cat)a).jump();

// 接口的只能调接口方法
Jumpping j = new Cat("Doppy","21");
j.jump();

// 一般用这个
Cat c = new Cat("James","18");
c.show();
c.eat();
c.jump();
}

}

183. 类和接口的关系

  • 类和类的关系:继承关系,只能一对一继承,但是可以多层继承。
  • 类和接口的关系: 可以实现多个接口。甚至可以在继承一个类的时候实现接口。(extends x implements inter1,inter2,inter3
  • 接口与接口的关系:可以单继承,也可以多继承。 (extends x,y,z)

184. 抽象类和接口的区别

抽象类和接口的区别

将类所具有的本身的功能设计为抽象类,将一些外部功能设计为接口。

抽象类是对事物的抽象,接口是对行为的抽象。

185.运动员和教练:案例分析

现在有乒乓球运动员和篮球运动员,乒乓球教练和篮球教练,跟乒乓球相关的需要学习英语。试着做出代码设计。

抽象类:人类:运动员、教练。

子类:乒乓球教练、篮球教练。

接口:学英语。

运动员与教练分析1
运动员与教练分析2

最后写测试类测试。

注意:谁不抽象,谁重写。

1
2
3
4
5
6
package 运动员与教练接口;

public interface English {
public abstract void speakEnglish();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package 运动员与教练接口;

public abstract class Human {
private String name;
private String age;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getAge() {
return age;
}

public void setAge(String age) {
this.age = age;
}

public Human(String name, String age) {
this.name = name;
this.age = age;
}

public Human(){}

public abstract void eat();

public void show(){
System.out.println("姓名"+name+"年龄"+age);
}
}

1
2
3
4
5
6
7
8
9
10
11
package 运动员与教练接口;

public abstract class Coach extends Human {
Coach(){}
Coach(String name, String age){
super(name, age);
}

public abstract void teach();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
package 运动员与教练接口;

public abstract class Sportsman extends Human {
public Sportsman() {
}

public Sportsman(String name, String age) {
super(name, age);
}

public abstract void study();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package 运动员与教练接口;

public class BBCoach extends Coach{
public BBCoach() {
}

public BBCoach(String name, String age) {
super(name, age);
}

@Override
public void eat() {
System.out.println("篮球教练吃饭");
}

@Override
public void teach() {
System.out.println("篮球教练教篮球");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package 运动员与教练接口;

public class BBSportsman extends Sportsman {
public BBSportsman() {
}

public BBSportsman(String name, String age) {
super(name, age);
}

@Override
public void eat() {
System.out.println("篮球运动员吃饭");
}

@Override
public void study() {
System.out.println("篮球运动员学习打篮球");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package 运动员与教练接口;

public class TTCoach extends Coach implements English{
public TTCoach() {
}

public TTCoach(String name, String age) {
super(name, age);
}

@Override
public void eat() {
System.out.println("乒乓球教练吃饭");
}

@Override
public void teach() {
System.out.println("乒乓球教练教乒乓球");
}

@Override
public void speakEnglish() {
System.out.println("乒乓球教练需要学习英语");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package 运动员与教练接口;

public class TTSportsman extends Sportsman implements English{
public TTSportsman() {
}

public TTSportsman(String name, String age) {
super(name, age);
}

@Override
public void eat() {
System.out.println("乒乓球运动员吃饭");
}

@Override
public void study() {
System.out.println("乒乓球运动员学乒乓球");

}

@Override
public void speakEnglish() {
System.out.println("乒乓球运动员学英语");
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package 运动员与教练接口;

public class test {
public static void main(String[] args) {
BBSportsman bbs = new BBSportsman("James","21");
bbs.show();
bbs.eat();
bbs.study();
System.out.println("----------------------------");
TTSportsman tts = new TTSportsman();
tts.setAge("19");
tts.setName("Long Ma");
tts.show();
tts.eat();
tts.study();
tts.speakEnglish();
System.out.println("----------------------------");
BBCoach bbc = new BBCoach("Popovich","80");
bbc.show();
bbc.eat();
bbc.teach();
System.out.println("----------------------------");
TTCoach ttc = new TTCoach("Guoliang Liu","45");
ttc.show();
ttc.eat();
ttc.teach();
ttc.speakEnglish();
}
}