一. 多态
-
定义
- 一个事物的多种形态
-
多态的前提
- 要有子父关系
- 要有方法重写
- 要有父类引用指向子类对象
-
演示
public class Father { public void method(){ System.out.println("父类method方法"); } } //子类继承父类 public class Son extends Father { //重写父类的方法 public void method(){ System.out.println("子类的method方法"); } } public static void main(String[] args) { //父类类型的变量引用子类类型的实例对象 Father father = new Son(); father.method(); }
-
注意事项
- 可以做哪些工作看父类类型
- 实际做工作的看子类对象
- 优点: 提高了代码的扩展性, 复用性, 可以当作形参,用来接收任意类型的子类对象
- 缺点: 不能使用子类的特有属性和方法
-
演示
- 学校有授课功能, 但是需要聘请老师讲课, 编程模拟
public class School { public void teach(Teacher teacher){ teacher.teach(); } } public class Teacher { public void teach(){ System.out.println("老师上课"); } } public class MusicTeacher extends Teacher{ public void teach() { System.out.println("优美的歌声从教室中飘出"); } } public class MathTeacher extends Teacher{ public void teach() { System.out.println("认真的讲解着每一个运算步骤"); } } public static void main(String[] args) { School school = new School(); //调用学校的授课功能, 传递一个音乐老师过去 school.teach(new MusicTeacher()); //调用学校的授课功能, 传递一个数学老师过去 school.teach(new MathTeacher()); }
-
测试题
- 动物都有吃饭的功能, 但是小狗吃的是狗粮, 小猫吃的猫粮,当我们将小猫小狗体貌特征遮盖住的时候, 如何判定吃东西的是小猫还是小狗? 编程模拟
二. 多态成员访问的特点
-
成员变量
- 编译看左边(父类) , 运行看左边(父类) (静态绑定)
- 一般中情况使用极少, 成员变量一般都是私有化的
public class Father { String name = "小红"; } public class Son extends Father { String name = "小明"; } public static void main(String[] args) { Father father = new Son(); String str = father.name; System.out.println(str); //小红 }
-
成员方法
- 编译看左边(父类), 运行看右边(子类), 动态绑定
- 子类中如果对父类中的方法进行了重写, 父类中的方法无论如何都无法被访问, 这也是java动态绑定的结果
- 动态绑定会选择最优执行方法, 只要子类重写了父类的方法, 无论在什么地方调用, 都会先找子类
public class Father { public void method(){ System.out.println("父类method方法"); } } public class Son extends Father { public void method(){ System.out.println("子类method方法"); } } public static void main(String[] args) { Father father = new Son(); father.method();//子类method方法 }
-
静态方法
- 编译看左边(父类),运行看左边(父类)
public class Father { public static void method(){ System.out.println("父类method方法"); } } public class Son extends Father { public static void method(){ System.out.println("子类method方法"); } } public static void main(String[] args) { Father father = new Son(); father.method();//父类method方法 //Father.method(); }
-
测试题
- 判断结果
package com.qianfeng.duotai; class Fu{ public void show() { System.out.println("fu show"); } } class Zi extends Fu { public void show() { System.out.println("zi show"); } public void method() { System.out.println("zi method"); } } class TestDemo { public static void main(String[] args) { Fu f = new Zi(); f.method(); f.show(); } }
- 判断结果
class A { public void show() { show2(); } public void show2() { System.out.println("我"); } } class B extends A { public void show2() { System.out.println("爱"); } } class C extends B { public void show() { super.show(); } public void show2() { System.out.println("你"); } } public static void main(String[] args) { A a = new B(); a.show(); B b = new C(); b.show(); }
三. 多态转型
-
向上转型
- 将子类对象看作是父类类型, 也就是我们平时使用的多态的形式
- 这种情况下, 无法调用子类特有的功能
-
向下转型
-
将父类引用指向的子类对象再转回子类类型
-
这种转型是有危险的, 因为是强制性的, 一旦转向的类型跟这个对象不匹配, 就会报错java.lang.ClassCastException (类型转换异常, 属于运行时异常)
public static void main(String[] args) { Father f = new Son(); //转回子类类型 Son son = f; // }
-
四. final关键字
-
定义
- final 表示最终的, 无法被修改的
-
final修饰的特点
- 修饰类, 类不能被继承
- 修饰变量, 变量就变成了常量, 只能被赋值一次(初始化的时候赋值 )
- 修饰方法, 方法不能被重写
-
final 修饰局部变量
- 基本数据类型 , 是值不能被改变
- 引用数据类型, 是地址值不能被改变, 对象中的属性可以改变
- final可以修饰形参
-
final 修饰成员变量的初始化时机
-
必须手动赋值
-
对象初始化完毕之前
-
类初始化完成前(静态)
public class Demo { final String name = "小红"; { //name = "小红"; } public Demo(){ //name = "小红"; } }
-
-
测试题
- 判断结果
public class Demo { final String name ="小红"; public void method(){ name = "小明"; System.out.println(name); } //final修饰变量的时候,只能赋一次值 public void method2(final String name){ System.out.println(name); final int age; age = 10; System.out.println(age); } } public static void main(String[] args) { Demo demo = new Demo(); demo.method(); demo.method2("小红"); }
五. 抽象类
-
定义
- 抽象类没有具体的代码实现, 只是规定了方法的基本属性, 然后由子类去实现具体的代码, 抽象类主要是为了定义规则而存在的
-
特点
- 抽象类和抽象方法必须用abstract 关键字修饰
- abstract class 类名{}
- abstract 返回追类型 方法名();
- 抽象类不一定有抽象方法, 有抽象方法的类一定是抽象类或者接口
- 抽象类不能实例化, 必须由子类继承并重写抽象方法来实例化
- 抽象类的子类
- 要么是抽象类
- 要么重写抽象类中的所有抽象方法(普通类)
- 抽象类和抽象方法必须用abstract 关键字修饰
-
演示
- 公司的员工必须都要有打卡和工作的功能, 所有员工都是使用指纹打卡, 但是工作的方式因岗位的不同而不同
public abstract class Employee { public void sign(){ System.out.println("指纹打卡"); } public abstract void work(); } public class Hr extends Employee{ @Override public void work() { System.out.println("招聘人才"); } } public class Coder extends Employee{ @Override public void work() { System.out.println("努力的敲代码"); } }
-
测试题
- 汽车工厂的已经将车的主体完成,汽车已经可以开动了, 后期需要根据不同的用途安装不同的部件, 货车需要安装货箱, 用来拉货, 客车需要安装座椅,用来拉人
-
抽象类成员方法的特点
- 抽象方法 , 强制要求子类做的事情
- 非抽象方法, 子类继承的方法, 提高代码的复用性
-
优点
- 强制子类实现父类的方法功能
- 提高代码的扩展性, 便于后期的维护
- 形成一套规范(重点)
-
测试题
- 具体事物:猫,狗
- 共性:姓名,年龄,吃饭 (抽象类中成员变量的使用和普通类是一样的)
- 猫的特性 : 抓老鼠
- 狗的特性 : 看家
六. java值传递的三种方式
-
基本数据类型值的传递
- 基本数据类型传递是值, 也就是将具体的值赋给变量名,所以变量名代表的是具体的值
-
引用数据类型传递的是地址值
- 当一个对象赋值给一个对象名, 是将这个对象在内存中的地址值传递给对象名
- 实例对象在对内存中是有一个16进制的地址值
-
String 值的传递
- String 比较特殊, 她虽然是一个引用变量, 但是她传递的是具体的数值
- String 首先是在对内存中创建一个对象,对象里面封装的是常量值, 然后将数值放入到常量池中, 再指向String
-
总结
- 基本数据类型传递的是值, 引用数据类型传递的是址
七. 接口
-
定义
- 接口其实就是抽象类的升级版, 接口里面都是抽象方法
- 从狭义上将来说, 接口就是指java 中的interface
- 从广义上的角度讲对外提供规则的都是接口
- 接口就是一套标准的规范(规则)
-
特点
- 接口用关键字interface表示
- interface 接口名{ }
- 接口中方法上的abstract关键字可以省略
- 类实现接口用implements表示
- class类名 implements 接口名{ }
- 接口不能实例化
- 接口按照多态的方法实例化
- 接口的子类
- 可以是接口,使用extends来继承
- 可以是抽象类, 但意义不大
- 可以是实体类, 要重写接口中的所有抽象方法( 主要使用 )
- 接口中的成员变量必须是静态的 最终 公共, 也就是常量
- static , final 关键字可以省略 (建议省略)
- 接口可以继承接口
- 接口用关键字interface表示
-
演示
//接口1 public interface MyInterface { //定义了静态常量 static final 可以省略 static final String NAME = "小红"; //定义了抽象方法 public void method(); //定义了抽象方法 public void method2(); } //接口2 继承了接口1 public interface MyInterface2 extends MyInterface { //定义了抽象方法 public void method2(); } //定义实现类实现接口 public class MyInterfaceSon implements MyInterface2{ //重写抽象方法 @Override public void method() { System.out.println("重写method抽象方法"); } //重写抽象方法 @Override public void method2() { System.out.println("重写method2抽象方法"); } }
-
测试题
- 定义老师规则接口,定义老师类 讲课方法, 辅导作业方法
- 定义实现的子类, 不同老师不同的讲课方式和辅导作业的方式
八. 类 , 接口之间的关系
-
类与类
- 继承关系, 只能单继承 ,不能多继承 ,但是可以多层继承
- 多层继承: 子类继承父类,父类继承祖父类
- 如果多个父类出现相同的方法,无法区别
-
类与接口
- 实现关系,可以单实现, 也可以多实现, 在继承类的同时,可以多实现
- 多个接口中出现了名称和参数列表相同的方法, 但是返回值不同, 会报错
-
接口与接口
- 继承关系 ,可以单继承, 也可以多继承
- 如果多个父类中出现了相同的,子类用谁的都可以
总结:
1. 多态
* 子类对象可以存到父类的变量中
* 前提条件
* 子父类关系
* 方法重写
* 父类引用指向子类对象
* 好处
* 提高代码的复用性和扩展性
* 缺点
-
不能使用子类对象的特有方法
2. 多态成员访问的特点
-
编译看左边,运行看左边
- 成员变量
- 静态方法
-
编译看左边, 运行看右边 ,只要子类中重写了,一定执行子类的方法
-
非静态成员方法 (全遮挡)
- 多态转型
- 向上转型 (子类转父类)
-
-
线下转型 (父类转子类,有危险), 转之前,要使用 instanceof关键字判断一下
4. final
-
最终的, 无法被改变 , 只能赋值一次
-
修饰的特性
- 修饰类, 类不能被继承
- 修饰方法, 方法不能被重写
- 修饰变量, 变量只能赋值一次
-
修饰成员变量时
- 在初始化完毕之前必须要赋值
- 静态是类初始化完毕前
-
非静态是对象初始化完毕前
- 抽象类
- abstract关键字
- 制定规则
- 一个类中如果有抽象方法,这个类也必须是抽象类
- 抽象类中可以没有抽象方法
- 抽象不能实例化(创建对象) , 不安全, 抽象方法用不了
- 抽象类的子类可以是抽象类, 不用重写抽象方法
-
-
抽象类的子类可以是非抽象类, 必须重写抽象方法
6. java传递值得方式
-
基本数据类型传递的是值, 引用数据类型传递的是址, String稍微特殊
7. 接口
-
interface implements
-
接口中全部都是抽象方法
-
接口中的成员变量
- 都是公开的, 静态的, 最终的 public static final
-
作用
- 指定规则
- 思考的过程
-
代码的框架
-
我们在思考过程中, 用来记录业务逻辑.
- 类和接口之间的关系
- 类和类: 继承 单继承, 多层继承
- 类和接口: 实现, 可以多实现
- 接口和接口: 继承, 可以多继承
-
作业
-
第一题
- 一档选秀节目, 设计了一个平台供参与者展示才艺, 不同的参与者有不同的才艺. 使用多态编程模拟
-
第二题
- 学生都有学习和做作业的能力 , 但是学习的方式不同, 使用抽象类的方法模拟编程
-
第三题
- 创建一个乐器接口 Instrument, 定义演奏方法play, 定义两个实现类 钢琴 Piano, 小提琴 Violin ,分别实现乐器接口,并做出不同的演奏
-
第四题
- 国家规定, 汽车必须能点火, 能开动, 国家将文件发送到汽车厂商的手中, 厂商生产的汽车必须符合要求, 可以有特性功能, 编程模拟
-
扩展题
class A{ public String show(D obj){ //D obj = new D(); return ("A and D"); } public String show(A obj){ //A obj = new D(); return ("A abd A"); } } class B extends A{ public String show(B obj){ return ("B and B"); } public String show(A obj){ return ("B and A"); } } class C extends B{ } class D extends B{ } 问题:以下输出结果是什么? A a1 = new A(); A a2 = new B(); B b = new B(); C c = new C(); D d = new D(); System.out.println(a1.show(b)); ① A abd A System.out.println(a1.show(c)); ② A abd A System.out.println(a1.show(d)); ③ A and D System.out.println(a2.show(b)); ④ B and A System.out.println(a2.show(c)); ⑤ B and A System.out.println(a2.show(d)); ⑥ A and D System.out.println(b.show(b)); ⑦ B and B System.out.println(b.show(c)); ⑧ B and B System.out.println(b.show(d)); ⑨ A and D //能执行哪些方法,看变量的类型 //如果有多态,那么实际执行那个方法看子类 //如果有多个方法可行,找最合适的,也就是最接近的
网友评论