前言

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

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

169. 多态

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

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

多态的前提和实现

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

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

package 多态;

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

package 多态;

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

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

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

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

    171. 多态的好处和弊端

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

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

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

代码:

package 多态;

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

package 多态;

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

package 多态;

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

package 多态;

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

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. 多态中的转型

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

代码:

package 多态强转;

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

package 多态强转;

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

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. 定义测试类。
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);
    }
}

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("猫玩玩具");
    }
}

package 猫与狗多态;

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

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


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

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类,继承,无参带参,重写吃饭
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);
    }
}

package 猫和狗抽象类;

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

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

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

package 猫和狗抽象类;

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

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

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

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类,继承,无参带参,重写吃饭,跳高 代码只写了个猫的,以猫为例。 ```java 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);
} }

```java
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("猫跳高");
    }
}

package 猫和狗接口;

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

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

最后写测试类测试。

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

package 运动员与教练接口;

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

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);
    }
}

package 运动员与教练接口;

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

    public abstract void teach();
}

package 运动员与教练接口;

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

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

    public abstract void study();
}

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("篮球教练教篮球");
    }
}

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("篮球运动员学习打篮球");
    }
}

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("乒乓球教练需要学习英语");
    }
}

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("乒乓球运动员学英语");
    }
}

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();
    }
}