Java基础学习第九天——多态,抽象类,接口

来源:互联网 发布:天猫双11数据直播 编辑:程序博客网 时间:2024/05/18 00:23
文档版本 开发工具 测试平台 工程名字 日期 作者 备注 V1.0 2016.02.29 lutianfei none

final 关键字

  • final关键字,可以修饰成员变量成员方法

  • 特点:

    • 修饰的,类不能被继承
    • 修饰的变量,变量就变成了常量,只能被赋值一次
    • 修饰的方法,方法不能被重写

final关键字面试题

  • Eg1: final修饰局部变量

    • 方法内部,该变量不可以被改变
    • 方法声明上,分为基本类型引用类型作为参数的情况
      • 基本类型,是不能被改变
      • 引用类型,是地址值不能被改变,但是该对象堆内存的值可以改变。
  • Eg2: final修饰变量的初始化时机

    • 对象构造完毕前即可
  • Eg 3:程序说明

class Student {    int age = 10;}class FinalTest {    public static void main(String[] args) {        //局部变量是基本数据类型        int x = 10;        x = 100;        System.out.println(x);        final int y = 10;        //无法为最终变量y分配值        //y = 100;        System.out.println(y);        System.out.println("--------------");        //局部变量是引用数据类型        Student s = new Student();        System.out.println(s.age);        s.age = 100;        System.out.println(s.age);        System.out.println("--------------");        final Student ss = new Student();        System.out.println(ss.age);        ss.age = 100;        System.out.println(ss.age);        //重新分配内存空间        //无法为最终变量ss分配值        ss = new Student();    }}


多态

多态概述

  • 某一个事物,在不同时刻表现出来的不同状态。
    • 举例:
      • 猫可以是猫的类型。猫 m = new 猫();
      • 同时猫也是动物的一种,也可以把猫称为动物。
        • 动物 d = new 猫();
  • 多态前提体现
    • 继承关系
    • 方法重写
    • 父类引用指向子类对象
      • Fu f = new Zi();

多态的分类

  • 具体类多态:
    • class Fu{}
    • class Zi extends Fu{}
    • Fu f = new Zi();
  • 抽象类多态:
    • abstract class Fu{}
    • class Zi extends Fu{}
    • Fu f = new Zi();
  • 接口多态:
    • interface Fu{}
    • class Zi implements Fu{}
    • Fu f = new Zi();

多态中的成员访问特点

  • A:成员变量:编译看左边,运行看左边

  • B:构造方法:创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化

  • C:成员方法: 编译看左边,运行看右边。由于成员方法存在方法重写,所以它运行看右边。

  • D:静态方法:编译看左边,运行看左边。

    • (静态和类相关,算不上重写,所以,访问还是左边的)
  • eg:

class Fu {    public int num = 100;    public void show() {        System.out.println("show Fu");    }    public static void function() {        System.out.println("function Fu");    }}class Zi extends Fu {    public int num = 1000;    public int num2 = 200;    public void show() {        System.out.println("show Zi");    }    public void method() {        System.out.println("method zi");    }    public static void function() {        System.out.println("function Zi");    }}class DuoTaiDemo {    public static void main(String[] args) {        //要有父类引用指向子类对象。        //父 f =  new 子();        Fu f = new Zi();        System.out.println(f.num);        //找不到符号        //System.out.println(f.num2);        f.show();        //找不到符号,不能使用子类独有的方法。        //f.method();        f.function();    }}/** 运行结果:100show Zifunction Fu*/


多态的优缺点

  • 多态的好处
    • 提高了程序的维护性(由继承保证)
    • 提高了程序的扩展性(由多态保证)
  • 多态的弊端

    • 父类不能访问子类特有功能
  • 如何才能访问子类的特有功能呢?

    • 创建子类对象,调用方法即可。(然而很多时候不合理,且太占内存)
    • 向下转型:把父类的引用强制转换为子类的引用。
      • Zi z = (Zi)f; //要求该f必须是能够转换为Zi的
  • 现象: 子可以当做父使用,父不能当作子使用。

多态中的转型问题

  • 向上转型
    • 从子到父
    • 父类引用指向子类对象
  • 向下转型

    • 从父到子
    • 父类引用转为子类对象
  • 孔子装爹案例(经典,精辟

//多态的问题理解:    class 孔子爹 {        public int age = 40;        public void teach() {            System.out.println("讲解JavaSE");        }    }    class 孔子 extends 孔子爹 {        public int age = 20;        public void teach() {            System.out.println("讲解论语");        }        public void playGame() {            System.out.println("英雄联盟");        }    }    //Java培训特别火,很多人来请孔子爹去讲课,这一天孔子爹被请走了    //但是还有人来请,就剩孔子在家,价格还挺高。孔子一想,我是不是可以考虑去呢?    //然后就穿上爹的衣服,带上爹的眼睛,粘上爹的胡子。就开始装爹    //向上转型:父类引用指向子类对象    孔子爹 k爹 = new 孔子();    //到人家那里去了    System.out.println(k爹.age); //40    k爹.teach(); //讲解论语,一讲就露馅。    //k爹.playGame(); //这是儿子才能做的,一做就报错!    //讲完了,下班回家了    //脱下爹的装备,换上自己的装备    //向下转型:父类引用转为子类对象    孔子 k = (孔子) k爹;    System.out.println(k.age); //20    k.teach(); //讲解论语    k.playGame(); //英雄联盟



  • 多态案例的内存图解


  • 多态练习:猫狗案例
class Animal {    public void eat(){        System.out.println("吃饭");    }}class Dog extends Animal {    public void eat() {        System.out.println("狗吃肉");    }    public void lookDoor() {        System.out.println("狗看门");    }}class Cat extends Animal {    public void eat() {        System.out.println("猫吃鱼");    }    public void playGame() {        System.out.println("猫捉迷藏");    }}class DuoTaiTest {    public static void main(String[] args) {        //定义为狗        Animal a = new Dog();        a.eat();        System.out.println("--------------");        //还原成狗        Dog d = (Dog)a;        d.eat();        d.lookDoor();        System.out.println("--------------");        //变成猫        a = new Cat();        a.eat();        System.out.println("--------------");        //还原成猫        Cat c = (Cat)a;        c.eat();        c.playGame();        System.out.println("--------------");    }}


  • 不同地方饮食文化不同的案例
class Person {    public void eat() {        System.out.println("吃饭");    }}class SouthPerson extends Person {    public void eat() {        System.out.println("炒菜,吃米饭");    }    public void jingShang() {        System.out.println("经商");    }}class NorthPerson extends Person {    public void eat() {        System.out.println("炖菜,吃馒头");    }    public void yanJiu() {        System.out.println("研究");    }}class DuoTaiTest2 {    public static void main(String[] args) {        //测试        //南方人        Person p = new SouthPerson();        p.eat();        System.out.println("-------------");        SouthPerson sp = (SouthPerson)p;        sp.eat();        sp.jingShang();        System.out.println("-------------");        //北方人        p = new NorthPerson();        p.eat();        System.out.println("-------------");        NorthPerson np = (NorthPerson)p;        np.eat();        np.yanJiu();    }}/*运行结果:炒菜,吃米饭-------------炒菜,吃米饭经商-------------炖菜,吃馒头-------------炖菜,吃馒头研究*/


多态中继承

  • 继承的时候:

    • 子类中有和父类中一样的方法,叫重写
    • 子类中没有而父类方法,方法就被继承过来了。
  • Eg:(重难点)

class A {    public void show() {        show2();    }    public void show2() {        System.out.println("我");    }}class B extends A {    /* 此处完全可以认为B中是有show方法的,继承自A。    public void show() {        show2(); //因为内存堆中new的是class C,所以调用的将是C的show2()。    }    */    public void show2() {        System.out.println("爱");    }}class C extends B {    public void show() {        super.show();    }    public void show2() {        System.out.println("你");    }}public class DuoTaiTest4 {    public static void main(String[] args) {        A a = new B();        a.show();        B b = new C();        b.show();    }}// 运行结果://爱//你


抽象类

抽象类概述

  • 动物本身并不是一个具体的事物,而是一个抽象的事物。只有真正的猫,狗才是具体的动物。同理,我们也可以推想,不同的动物吃的东西应该是不一样的,所以,我们不应该在动物类中给出具体体现,而是应该给出一个声明即可。在Java中,一个没有方法体(连大括号也没有)的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类

抽象类特点

  • 抽象类抽象方法必须用abstract关键字修饰

    • 格式
      • abstract class 类名 {}
      • public abstract void eat();
  • 抽象类不一定有抽象方法,有抽象方法的类一定是抽象类

  • 抽象类不能实例化(抽象类如何实例化呢?)

    • 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态
    • 抽象类有构造方法,其作用是为了用于子类访问父类数据的初始化
  • 抽象类的子类

    • 要么是抽象类
    • 要么重写抽象类中的所有抽象方法
//abstract class Animal //抽象类的声明格式abstract class Animal {    //抽象方法    //public abstract void eat(){} //空方法体,这个会报错。抽象方法不能有主体    public abstract void eat();    public Animal(){}}//子类是抽象类abstract class Dog extends Animal {}//子类是具体类,重写抽象方法class Cat extends Animal {    public void eat() {        System.out.println("猫吃鱼");    }}class AbstractDemo {    public static void main(String[] args) {        //创建对象        //Animal是抽象的; 无法实例化        //Animal a = new Animal();        //通过多态的方式        Animal a = new Cat();        a.eat();    }}


抽象类的成员特点

  • 成员变量
    • 可以是变量
    • 也可以是常量
  • 构造方法
    • 有构造方法,但是不能实例化
    • 那么,构造方法的作用是什么呢?
      • 用于子类访问父类数据的初始化
  • 成员方法

    • 可以有抽象方法 作用:限定子类必须完成某些动作
    • 也可以有非抽象方法 提高代码复用性
  • 抽象定义类练习:

//定义抽象的动物类abstract class Animal {    //姓名    private String name;    //年龄    private int age;    public Animal() {}    public Animal(String name,int age) {        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    //定义一个抽象方法    public abstract void eat();}//定义具体的狗类class Dog extends Animal {    public Dog() {}    public Dog(String name,int age) {        super(name,age); //重要知识点!!!    }    public void eat() {        System.out.println("狗吃肉");    }}//定义具体的猫类class Cat extends Animal {    public Cat() {}    public Cat(String name,int age) {        super(name,age);    }    public void eat() {        System.out.println("猫吃鱼");    }}//测试类class AbstractTest {    public static void main(String[] args) {    //测试狗类      //具体类用法        //方式1:        Dog d = new Dog();        d.setName("旺财");        d.setAge(3);        System.out.println(d.getName()+"---"+d.getAge());        d.eat();        //方式2:        Dog d2 = new Dog("旺财",3);        System.out.println(d2.getName()+"---"+d2.getAge());        d2.eat();        System.out.println("---------------------------");      //抽象类用法        //方式1:        Animal a = new Dog();        a.setName("旺财");        a.setAge(3);        System.out.println(a.getName()+"---"+a.getAge());        a.eat();        //方式2:        Animal a2 = new Dog("旺财",3);        System.out.println(a2.getName()+"---"+a2.getAge());        a2.eat();        //练习:测试猫类    }}


  • 抽象教师类练习:
//定义抽象的老师类abstract class Teacher {    //姓名    private String name;    //年龄    private int age;    public Teacher() {}    public Teacher(String name,int age) {        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    //抽象方法    public abstract void teach();}//基础班老师类class BasicTeacher extends Teacher {    public BasicTeacher(){}    public BasicTeacher(String name,int age) {        super(name,age);    }    public void teach() {        System.out.println("基础班老师讲解JavaSE");    }}//就业班老师类class WorkTeacher extends Teacher {    public WorkTeacher(){}    public WorkTeacher(String name,int age) {        super(name,age);    }    public void teach() {        System.out.println("就业班老师讲解JavaEE");    }}class AbstractTest2 {    public static void main(String[] args) {        //测试(多态)        //基础班老师        Teacher t = new BasicTeacher();        t.setName("刘意");        t.setAge(30);        System.out.println(t.getName()+"---"+t.getAge());        t.teach();        System.out.println("--------------");        t = new BasicTeacher("刘意",30);        System.out.println(t.getName()+"---"+t.getAge());        t.teach();        System.out.println("--------------");        //就业班老师        t = new WorkTeacher();        t.setName("林青霞");        t.setAge(27);        System.out.println(t.getName()+"---"+t.getAge());        t.teach();        System.out.println("--------------");        t = new WorkTeacher("林青霞",27);        System.out.println(t.getName()+"---"+t.getAge());        t.teach();    }}


抽象类的几个小问题

  • 一个类如果没有抽象方法,可以定义为抽象类?如果可以,有什么意义?

    • 可以
    • 禁止创建对象
  • abstract不能和哪些关键字共存

    • private 冲突
    • final 冲突
    • static 无意义(通过类名直接访问没有内容的方法体)


接口

接口概述

  • 狗一般就是看门,猫一般就是作为宠物。但是,现在有很多的驯养员或者是驯兽师,可以训练出:猫钻火圈,狗跳高,狗做计算等。而这些额外的动作,并不是所有猫或者狗一开始就具备的,这应该属于经过特殊的培训训练出来的。所以,这些额外的动作定义到动物类中就不合适,也不适合直接定义到猫或者狗中,因为只有部分猫狗具备这些功能。
    所以,为了体现事物功能的扩展性,Java中就提供了接口来定义这些额外功能,并不给出具体实现,将来哪些猫狗需要被培训,只需要这部分猫狗把这些额外功能实现即可。

接口特点

  • 接口用关键字interface表示

    • 格式:interface 接口名 {}
  • 类实现接口用implements表示

    • 格式:class 类名 implements 接口名 {}
  • 接口不能实例化(接口如何实例化呢?)

    • 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,接口多态
  • 接口的实现类(子类):

    • 抽象类:实现接口,但意义不大
    • 具体类:重写接口中的所有抽象方法
  • 补充:多态的三种形式

    • 具体类多态(几乎没有)
    • 抽象类多态(常用)
    • 接口类多态(最常用 )

接口成员特点

  • 成员变量
    • 只能是常量
    • 默认修饰符 public static final
  • 构造方法
    • 没有构造方法,因为接口主要是扩展功能的,而没有具体存在。
    • 所有的类都默认继承自一个类:Object。(类Object 是类层次结构的根类。每个类都使用Object作为超类)
  • 成员方法
    • 只能是抽象方法
    • 默认修饰符 public abstract


类与类,类与接口 以及 接口与接口 的关系

  • 类与类

    • 继承关系,只能单继承,但是可以多层继承
  • 类与接口

    • 实现关系
      • 可以单实现,也可以多实现
      • 还可以在继承一个类的同时实现多个接口。
  • 接口与接口

    • 继承关系,可以单继承,也可以多继承

抽象类和接口的区别

  • 成员区别

    • 抽象类
      • 成员变量:变量,常量;
      • 构造方法:可以有
      • 成员方法:可以是抽象方法,也可以是非抽象方法;
    • 接口
      • 成员变量:只可以是常量;
      • 构造方法:没有
      • 成员方法:只能是抽象方法
  • 设计理念区别

    • 抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能
    • 接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能
  • 跳高猫练习:

/*    猫狗案例,加入跳高的额外功能    分析:从具体到抽象        猫:            姓名,年龄            吃饭,睡觉        狗:            姓名,年龄            吃饭,睡觉        由于有共性功能,所以,我们抽取出一个父类:        动物:            姓名,年龄            吃饭();            睡觉(){}        猫:继承自动物        狗:继承自动物        跳高的额外功能是一个新的扩展功能,所以我们要定义一个接口        接口:            跳高        部分猫:实现跳高        部分狗:实现跳高    实现;        从抽象到具体    使用:        使用具体类*///定义跳高接口interface Jumpping {    //跳高功能    public abstract void jump();}//定义抽象类abstract class Animal {    //姓名    private String name;    //年龄    private int age;    public Animal() {}    public Animal(String name,int age) {        this.name = name;        this.age = age;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public int getAge() {        return age;    }    public void setAge(int age) {        this.age = age;    }    //吃饭();    public abstract void eat();    //睡觉(){}    public void sleep() {        System.out.println("睡觉觉了");    }}//具体猫类class Cat extends Animal {    public Cat(){}    public Cat(String name,int age) {        super(name,age);    }    public void eat() {        System.out.println("猫吃鱼");    }}//具体狗类class Dog extends Animal {    public Dog(){}    public Dog(String name,int age) {        super(name,age);    }    public void eat() {        System.out.println("狗吃肉");    }}//有跳高功能的猫class JumpCat extends Cat implements Jumpping {    public JumpCat() {}    public JumpCat(String name,int age) {        super(name,age);    }    public void jump() {        System.out.println("跳高猫");    }}//有跳高功能的狗class JumpDog extends Dog implements Jumpping {    public JumpDog() {}    public JumpDog(String name,int age) {        super(name,age);    }    public void jump() {        System.out.println("跳高狗");    }}class InterfaceTest {    public static void main(String[] args) {        //定义跳高猫并测试        JumpCat jc = new JumpCat();        jc.setName("哆啦A梦");        jc.setAge(3);        System.out.println(jc.getName()+"---"+jc.getAge());        jc.eat();        jc.sleep();        jc.jump();        System.out.println("-----------------");        JumpCat jc2 = new JumpCat("加菲猫",2);        System.out.println(jc2.getName()+"---"+jc2.getAge());        jc2.eat();        jc2.sleep();        jc2.jump();        //定义跳高狗并进行测试的事情自己完成。    }}
  • 运行结果
1 0
原创粉丝点击