Java基础学习第九天——多态,抽象类,接口
来源:互联网 发布:天猫双11数据直播 编辑:程序博客网 时间:2024/05/18 00:23
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
- Java基础学习第九天——多态,抽象类,接口
- 第九天:JAVA中的多态,抽象类和接口
- JAVA基础———第九天
- java基础第九天——泛型
- java学习总结——第九天
- java基础学习——内部类、抽象类、接口
- java基础学习总结——接口和抽象类
- Java 基础 第九天
- java基础第九天
- Java基础——抽象类&接口
- 黑马程序员——java基础学习笔记——第九天
- 国嵌视频学习第九天——UBOOT基础
- Java基础学习笔记09——(final关键字,多态,抽象类,接口)
- 黑马程序员—java基础学习--抽象类(abstract)、接口(interface)、多态
- java基础学习-抽象类、接口
- Java学习第九天
- JAVA 学习第九天
- JAVA学习第九天
- ViewPager 配合FragmentPagerAdapter
- 餐厅点餐
- Linux技术——tcpdump命令详解
- 网页爬虫及其用到的算法和数据结构
- 模板与泛型编程2
- Java基础学习第九天——多态,抽象类,接口
- Objective-C 单例模式
- Android中Intent传递对象的两种方法(Serializable,Parcelable)
- Ubuntu 下搭建django开发环境
- iOS开发学习之导航控制器和应用程序的生命周期
- ADO访问Excel 2007
- CocoaPods的安装(以下命令均在终端下操作)
- 蓝桥杯 地宫取宝
- BZOJ1044/HAOI2008木棍分割