Java学习笔记(五)

181 阅读5分钟

抽象类

动物具体移动方式没法在动物类中去写,所有动物类和其方法都是抽象化处理,就不写具体的实现。

  • 用abstract关键字修饰一个类时,这个类叫做抽象类。
  • 用abstract关键字修饰一个方法时,这个方法叫做抽象方法。
  • 不能被实例化
  • 只要类中有一个抽象的方法,那么这个类就必须是一个抽象类
public abstract class Animal {
    
    public abstract void move();

}

class Dog extends Animal {
    
    @Override
    public void move() {
        System.out.println("狗的移动方式是跑");
    }
}

class Fish extends Animal {
    
    @Override
    public void move() {
        System.out.println("鱼的移动方式是游");
    }
}

abstract class Bird extends Animal {

    @Override
    public void move() {

    }

    public abstract void test();  //只要类中有一个抽象方法,类就必须是一个抽象类
}

问题1:为什么抽象类不可以使用final关键字声明?

final是最终,他修饰的类不能被继承;而抽象类是用来被继承的,子类必须重写父类的抽象方法,并且提供方法体。

问题2:一个抽象类中可以定义构造器吗?

抽象类可以有构造方法,但不能实例化。

public abstract class Employee {

    int id;
    String name;
    double salary;

    public abstract void work();
}

class Manager extends Employee{

    double bonus;

    public void setManager(int id, String name, double salary, double bonus) {
        super.id = id;  //从父类继承的属性,用super
        super.name = name;
        super.salary = salary;
        this.bonus = bonus; //本类自己的属性,用this
    }

    public void getManager() {
        System.out.println(super.id);
        System.out.println(super.name);
        System.out.println(super.salary);
        System.out.println(this.bonus);
    }
    @Override
    public void work() {
        System.out.println("这是领导");
    }
}

class CommonEmployee extends Employee{

    public void setCommonEmployee(int id, String name, double salary) {
        super.id = id;
        super.name = name;
        super.salary = salary;
    }

    public void getCommonEmployee() {
        System.out.println(super.id);
        System.out.println(super.name);
        System.out.println(super.salary);
    }

    @Override
    public void work() {
        System.out.println("这是员工");
    }
}

模板方法设计模式

抽象类就像一个大纲,里面的抽象方法就是每个章节的标题,子类,去根据这些标题把每个章节细化出来。

public abstract class Template {
    public abstract void code();

    public final void getTime() {
        long start = System.currentTimeMillis();
        code();
        long end = System.currentTimeMillis();
        System.out.println("code方法执行的时间:" + (end - start));
    }
}

class TestTemplate extends Template {

    int k = 0;
    @Override
    public void code() {
        for (int i = 0; i < 50000; i++) {
            k += 1;
        }
    }
}

接口(interface)

抽象方法和常量值的定义的集合。

  • 从本质上讲,接口是一种特殊的抽象类,只包含常量和方法的定义,而没有变量和方法的实现。
  • 实现接口类:implements
  • 一个类可以实现多个接口,接口也可以继承其他接口。

接口的特点:

  • 用interface来定义
  • 接口中的所有成员变量都默认是由public static final修饰的
  • 接口中的所有方法都默认是由public abstract修饰的
  • 接口没有构造器
  • 接口采用多重继承机制

例子:用java描述会唱歌的厨子是个老师

public abstract class Person1 {
    int age;
    String name;
    String sex;

    public abstract void showInfo();
}
public interface Cooking {
    void fry();
}
public interface Singer {
    void sing();
}
public class SCTeacher extends Person1 implements Cooking, Singer {

    String course;  //教的科目


    public void setInfo(int age, String name, String sex, String course) {
        super.age = age;
        super.name = name;
        super.sex = sex;
        this.course = course;
    }
    @Override
    public void fry() {
        System.out.println("我会炒菜");
    }

    @Override
    public void sing() {
        System.out.println("我会唱歌");
    }

    @Override
    public void showInfo() {
        System.out.println("会唱歌的厨子的老师的信息是:");
        System.out.println(super.name);
        System.out.println(super.age);
        System.out.println(super.sex);
        System.out.println(this.course);
    }
}

总结:

  • 抽象类是对于一类事物的高度抽象,其中既有属性也有方法,当需要对一类事物抽象的时候,应该使用抽象类,好形成一个父类。
  • 接口是对方法的抽象,也就是对一系列动作的抽象。当需要对一系列动作抽象时,就使用接口,需要使用这些动作的类去实现相应的接口即可。

工厂模式

在真正的开发工作中,都是合作开发,每个开发人员写部分代码,大家集合在一起就是一个项目。

例如:在开发宝马车的过程中

/**
 * 宝马车的产品接口
 */
public interface BWM {
    //产品的信息介绍
    void showInfo();
}

/**
 * 构建具体车的类
 */
class BWM3i implements BWM{

    @Override
    public void showInfo() {
        System.out.println("这个是宝马3i系");
    }
}

class BWM5 implements BWM{

    @Override
    public void showInfo() {
        System.out.println("这个是宝马5系");
    }
}

class BWM7 implements BWM{

    @Override
    public void showInfo() {
        System.out.println("这个是宝马7系");
    }
}
/**
 * 汽车生产工厂接口
 */
public interface BWMFactory {
    BWM productBWM();
}

/**
 * 实现具体车型的生产工厂
 */
class BWM3Factory implements BWMFactory {

    @Override
    public BWM productBWM() {
        System.out.println("生产宝马3系车");
        System.out.println("改造3系车,定名为BWM3i型号");
        return new BWM3i();
    }
}

class BWM5Factory implements BWMFactory {

    @Override
    public BWM productBWM() {
        System.out.println("生产宝马5系车");
        return new BWM5();
    }
}

class BWM7Factory implements BWMFactory {

    @Override
    public BWM productBWM() {
        System.out.println("生产宝马7系车");
        return new BWM7();
    }
}
public class Test2 {
    public static void main(String[] args) {
        BWM bwm3 = new BWM3Factory().productBWM();
        bwm3.showInfo();
        BWM bwm5 = new BWM5Factory().productBWM();
        bwm5.showInfo();
        BWM bwm7 = new BWM7Factory().productBWM();
        bwm7.showInfo();
    }
}

输出:生产宝马3系车 改造3系车,定名为BWM3i型号 这个是宝马3i系 生产宝马5系车 这个是宝马5系 生产宝马7系车 这个是宝马7系

结论:通过工厂把new对象隔离,通过产品的接口可以接受不同实际产品的实现类,实例的类型的改变不影响其他合作开发人员的编程。

内部类

内部类可分为成员内部类(static成员内部类和非static成员内部类)、局部内部类匿名内部类

  • 可以声明为final
  • 可以定义多个
  • 可以声明为private或protected
public class Test3 {
    private int a;
    public int b;
    class A {
        int i;
        public void setTest3Fileds(){
            Test3.this.a = 1;
            Test3.this.b = 2;
        }
        public void set() {
            this.i = 10;
        }
    }

    //如果内部类是static的,就不能使用外部类非static的成员
    static class B {

    }

    public void setInfo() {
        new A().setTest3Fileds();  //外部类要用自己内部类的对象,得先new内部类的对象
        new A().set();
    }

    public void showInfo() {
        System.out.println(this.a);
        System.out.println(this.b);
    }

    public static void main(String[] args) {
        Test3 test3 = new Test3();
        test3.setInfo();
        test3.showInfo();
    }
}

内部类的作用:解决java不能多重继承的问题

/**
 * 现在类A想同时获得类B和类C的方法,并且重写
 * 可以使用内部类来变相实现类的多重继承,可以同时继承多个类
 */
class A {

    public void testB() {
        new InnerB().testB();
    }

    public void testC() {
        new InnerC().testC();
    }
    private class InnerB extends B {
        @Override
        public void testB() {
            System.out.println("这是重写之后的testB方法");
        }
    }
    private class InnerC extends C {
        @Override
        public void testC() {
            System.out.println("这是重写之后的testC方法");
        }
    }
}

class B {
    public void testB() {

    }

}

class C {
    public void testC() {

    }
}

public class Test4 {
    public static void main(String[] args) {
        A a = new A();
        a.testB();
        a.testC();
    }
}