java基础08--抽象类、接口、内部类

一、抽象类

介绍

#

使用场景

在这里插入图片描述

语法

在这里插入图片描述

抽象类的注意事项和细节(注意: 1,5,8)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

抽象类和普通类的区别

  • 不能被实例化,但可以作为父类引用指向子类对象
  • 修饰符不能有private,final,static
  • 如果有抽象方法抽象类一定要加上abstract
  • 继承过程中抽象方法一定要被实现或者继续抽象

模板设计模式

介绍

把通用的步骤放到抽象类的一个执行方法中,每个步骤定义成抽象方法,子类实现每个步骤的细节,当子类调用父类的执行方法时,如果遇到通用步骤就会调用子类的具体步骤来实现,(注意:新建对象时运行类型和编译类型都是子类的,只是调用了父类的方法而已,而通用步骤的方法子类对父类已经实现,所以调用的还是子类的)

案例

在这里插入图片描述

package com.bijing.static_.abstract_;

public abstract class Template {
    public static void main(String[] args) {
        AA aa = new AA();
        BB bb = new BB();
        aa.getTime();
        bb.getTime();
    }

    public void getTime() {
        long startTime = System.currentTimeMillis();
        job();
        long endTime = System.currentTimeMillis();
        System.out.println("运行时间:" + (endTime - startTime));
    }

    public abstract void job();
}

class AA extends Template {
    @Override
    public void job() {
        long sum = 0;
        for (long i = 0; i < 100000; i++) {
            sum += i;
        }
    }
}

class BB extends Template {
    @Override
    public void job() {
        long sum = 0;
        for (long i = 0; i < 1000000; i++) {
            sum += i;
        }
    }
}

二、接口

基本介绍

在这里插入图片描述
注意:

  1. 在接口中抽象方法可以不加abstract
  2. jdk8及以后可以有默认方法但是要加default关键字,如果是静态方法不用加default

接口使用的注意事项和使用细节(注意:4,6,8)

在这里插入图片描述
在这里插入图片描述

实现接口VS继承类

实现接口时对java单继承的补充

  • 当子类继承了父类就自动拥有了父类的功能
  • 如果子类需要拓展功能就需要通过实现接口的方式来拓展

在这里插入图片描述

接口的多态特性

有点类似向上转型和向下转型

在这里插入图片描述

多态传递

//I3实现了I1,I1继承了I2,所以接口I1和I2都可以使用I3的实例
//或者说I3==>I1->I2,I1和I2都可以使用I3的实例
interface I1 extends I2 {
}

interface I2 {
}

class I3 implements I1 {
}


public class Test {
    public static void main(String[] args) {
        I1 i1 = new I3();
        I2 i2 = new I3();
      }
  }

在这里插入图片描述

接口和抽象类的区别

  • 接口是对动作的抽象,抽象类是对本质的抽象
  • 接口中所有成员变量都是用public static final修饰的
  • 接口中没有构造器,没有main方法,因为它不是一个类
  • 抽象类是用来继承的(extends),接口是用来实现的(implements)
  • 接口是多继承的,抽象类是单继承的
  • 接口中声明默认方法要加default,静态方法可以不加
  • 接口中可以有静态方法不能有静态代码块,抽象类中可以有静态方法和静态代码块

三、内部类(重点、难点)

基本介绍

在这里插入图片描述

类的五大成员:属性,方法,构造器,代码块,内部类

内部类的分类

在这里插入图片描述

局部内部类

在这里插入图片描述
在这里插入图片描述

tips:因为在方法中,所以当成方法的一个局部变量,不过是以类的形式而存在的,所以可以访问外部类的成员但是不能添加访问修饰符,作用域也仅仅在定义它的方法或代码中,要使用也只能在方法中实例化对象

案例:
在这里插入图片描述


interface Plants {
    void say();
}

class Animal {
    private String name;

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

    public String getName() {
        return name;
    }

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

    void say() {
        System.out.println("我是动物" + getName());
    }
}

public class LocalInnerClass {

    public static void main(String[] args) {

        LocalInnerClass localInnerClass = new LocalInnerClass();
        localInnerClass.getAnimal();
        localInnerClass.getPlants();

    }

    //局部内部类--继承外部的一般类
    void getAnimal() {

        class Pig extends Animal {
            public Pig(String name) {
                super(name);
            }
        }
        Animal animal = new Pig("猪");
        animal.say();
    }

    //局部内部类--实现外部的接口
    void getPlants() {
        class Tree implements Plants {
            String name;

            public Tree(String name) {
                this.name = name;
            }

            @Override
            public void say() {
                System.out.println("我是植物" + this.name);
            }
        }
        Plants plants = new Tree("树");
        plants.say();
    

}

匿名内部类(重要!!!)

匿名内部类的使用

在这里插入图片描述

所谓的匿名实则是系统给的我们不知道而已,系统分配为***$1
在这里插入图片描述
在这里插入图片描述

//前提:必须继承一个父类或实现一个接口
interface Plants02 {
    String name = "apple tree";

    void say();
}

public class AnonymousInnerClass {
    int a = 1;
    String name = "pear tree";

    public static void main(String[] args) {
        AnonymousInnerClass anonymousInnerClass = new AnonymousInnerClass();
        anonymousInnerClass.getAnimal02();
        anonymousInnerClass.getPlant02();
    }

    //匿名内部类
    void getAnimal02() {
        //继承类式的
        Animal02 dog = new Animal02("二狗") {
            public void say() {
                int a = 10;
                System.out.println("我是" + getName());
                System.out.println(a);//10
                System.out.println(AnonymousInnerClass.this.a);//1
            }

            public void sayName() {
            }
        };
        dog.say();
//        dog.sayName(),报错是因为dog的编译类型是Animal02,它没有sayName()方法
    }

    void getPlant02() {
        //实现接口式的
        Plants02 tree = new Plants02() {
            @Override
            public void say() {
                System.out.println("我是树");
                System.out.println(name);//apple tree
                System.out.println(AnonymousInnerClass.this.name);//pear tree
            }
        };
        tree.say();

        //lambda表达式
        Plants02 trees = () -> System.out.println("我是树");
    }

}

class Animal02 {
    private String name;

    public Animal02(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

    void say() {
        System.out.println("我是动物" + getName());
    }
}

注意和匿名对象的区别

        //下面的运行类型是Tiger
        Animal animal2 = new Tiger();
        //下面的运行类型是Outer$2
        Animal animal3 = new Tiger() {
        };
匿名内部类使用的注意事项和细节

tips:匿名内部类一般都是new 接口名/父类名 (){},创建出来的匿名内部类是“儿子”
在这里插入图片描述

 public void f1() {
 		//这边是类 
        Person p = new Person() {
            @Override
            public void hi() {
                System.out.println("内部hi() ");
            }
        };
        p.hi();
        //匿名内部类本身也是对象
        new Person() {
            @Override
            public void hi() {
                System.out.println("新的内部hi() ");
            }
        }.hi();
    }

在这里插入图片描述
在这里插入图片描述

匿名内部类的实践

在这里插入图片描述
和传统方法对比:

interface Plant { 
    void show();
}

public class Use_ {
    public static void main(String[] args) {
        //使用匿名内部类
        f1(new Plant() {
            @Override
            public void show() {
                System.out.println("wo shi plant");
            }
        });
        //传统方法
        f1(new Tree());
    }

    public static void f1(Plant plant) {
        plant.show();
    }
}

//传统方法
class Tree implements Plant {
    @Override
    public void show() {
        System.out.println("wo shi tree");
    }
}

成员内部类

在这里插入图片描述

public class OuterClass {
    int a = 1;

    public static void main(String[] args) {
        //调用成员内部类方法
        OuterClass outerClass = new OuterClass();
        outerClass.useInnerClass();
        //创建成员内部类对象,使用成员内部类属性,方法
        OuterClass.InnerClass innerClass = outerClass.new InnerClass();
        System.out.println(innerClass.name);
        innerClass.say();
    }

    public void useInnerClass() {
        InnerClass innerClass = new InnerClass();
        innerClass.say();
    }

    class InnerClass {
        String name = "内部类";
        int a = 10;

        void say() {
            System.out.println("我是内部类");
            System.out.println(a);//10
            System.out.println(OuterClass.this.a);//1
        }
    }
}

class OtherOuterClass {
    public static void main(String[] args) {
        // 外部其他类中使用
        OuterClass outerClass = new OuterClass();
        outerClass.useInnerClass();
        //创建成员内部类对象,使用成员内部类属性,方法
        OuterClass.InnerClass innerClass = outerClass.new InnerClass();
        System.out.println(innerClass.name);
        innerClass.say();
    }
}

在这里插入图片描述
第五点:
在这里插入图片描述

第六点:

class OuterClass {
    public InnerClass02 getInnerClass() {
        return new InnerClass02();
    }

    class InnerClass {
    }

    class InnerClass02 {
    }
}

class Visit {
    public static void main(String[] args) {
        OuterClass outerClass = new OuterClass();
        //方式一
        OuterClass.InnerClass innerClass = outerClass.new InnerClass();
        //方式二
        OuterClass.InnerClass02 innerClass02 = outerClass.getInnerClass();
    }
}

静态内部类

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

public class StaticInnerClass {
    static int a = 1;

    public static void main(String[] args) {
        //静态内部类对象创建及使用
        InnerClass innerClass = new InnerClass();
        innerClass.say();
        StaticInnerClass.InnerClass innerClass1 = new InnerClass();
        innerClass1.say();
    }

    static class InnerClass {
        int a = 10;

        void say() {
            System.out.println("我是静态内部类");
            System.out.println(a);//10
            System.out.println(StaticInnerClass.a);//1
        }
    }
}

//在其他外部内中使用静态内部类
class OtherOuterClass_ {
    public static void main(String[] args) {
        StaticInnerClass.InnerClass innerClass = new StaticInnerClass.InnerClass();
        innerClass.say();
    }
}


在这里插入图片描述