一、多态
1、认识多态
①什么是多态?
同类型的对象,表现出的不同形态。
②多态的表现形式
父类类型 对象名称 =子类对象; |
③多态的前提
- 有继承关系
- 有父类引用指向子类对象 Fu f =new Zi ( ) ;
- 有方法重写
register(s); register(t); register(a); public static void register( Person p){ p.show( ); //可以根据不同的对象调用不同的方法 } ⭐当我们调用方法的时候方法的参数是一个类的名字,此时可以传递这个类所有的子类对象 |
好处:使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利。
2、⭐多态调用成员的特点
- 变量调用:编译看左边,运行也看左边。
- 方法调用:编译看左边,运行看右边。
理解 Animal a = new Dog( ); 用a去调用变量和方法,a是Animal类型的,所以默认从Animal这个类中去找 成员变量:在子类的对象中,会把父类的成员变量也继承下去的。 父:name 子:name 成员方法:如果子类对方法进行了重写,那么在虚方法表中是会把父类的方法进行覆盖的。 |
3、多态的优势和弊端
①多态的优势
- 在多态形式下,右边对象可以实现解耦合,便于扩展和维护。
Person p = new Student( ); //只需改变红色的部分 p.work; //业务逻辑发生改变时,后续代码无需修改 |
- ⭐⭐定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体现多态的扩展性与便利。
②多态的弊端——不能调用子类的特有功能
解决方案:变回子类类型就可以了 例如: Animal a = new Dog( );——> Dog d =new Dog( );
------------------------------------------------------------------- a.eat( ); ——>d.lookhome( );
有一个判断使类型转化异常少出现一些 ——⭐⭐判断关键字 instanceof
if(a instanceof Dog){ Dog d=(Dog) a; d.lookHome( ); }else if(a instanceof Cat){ Cat d=(Cat) a; c.catchMouse( ); }else{ System.out.printIn("没有这个类型,无法转换"); } | //新特性 //先判断a是否为Dog类型,如果是,则强转成Dog类型,转换之后变量名为d //如果不是,则不强转,结果直接是false if(a instanceof Dog d){ d.lookHome( ); }else if(a instanceof Cat c){ c.catchMouse( ); }else{ System.out.printIn("没有这个类型,无法转换"); } |
③引用数据类型的类型转换,有几种方式?
自动类型转换、强制类型转换
Person p =new Student( ); 自动类型转换 Student s =(Student)p; 强制类型转换 |
④强制类型转换能解决什么问题?
- 可以转换成真正的子类类型,从而调用子类独有功能。
- 转换类型与真实对象类型不一致会报错
-
转换的时候用instanceof关键字进行判断
二、包和final
1、什么是包?
①包的作用?
包就是文件夹。用来管理各种不同功能的Java类,方便后期代码维护
②包名的规则:
- 公司域名反写+包的作用,需要全部英文小写,见名知意。
package com.itztt.domain; public class Student{ 全类名/全限定名 私有化成员变量 com.itheima.domain.Student 构造方法 全类名 = 包名 + 类名 成员方法 } |
使用其他类的规则
使用其他类时,需要使用全类名。
import com.itztt.domain.Student; public class Test{ public static void main(String[ ] args){ String s = new Student( ); } } |
③什么时候需要导包?什么时候不需要导包?
- 使用同一个包中的类时,不需要导包。
- 使用java.lang包中的类时,不需要导包。
- 其他情况都需要导包。
- 如果同时使用两个包中的同名类,需要用全类名。(了解,很少出现)
2、final
- final修饰 方法:表明该方法是最终方法,不能被重写
- final修饰 类:表明是最终类,不能被继承
- final修饰 变量:叫做常量,只能被赋值一次
①常量
实际开发中,变量一般作为系统的配置信息,方便维护,提高可读性。
常量的命名规范:
- 单个单词:全部大写
- 多个单词:全部大写,单词之间用下划线隔开
细节:
- final修饰的变量是基础类型:那么变量存储的数据值不能发生改变。
- final修饰的变量是引用类型:那么变量存储的地址值不能发生改变,对象内部的可以改变。
核心:
常量记录的数据是不能发生改变的。
三、权限修饰符和代码块
1、权限修饰符的分类
有四种作用范围由小到大(private<空着不写<protected<public)
缺省/默认
修饰符 | 同一个类中 | 同一个包中 其他类 | 不同包中的 子类 | 不同包下的 无关类 |
private | √ | |||
空着不写 | √ | √ | ||
protected | √ | √ | √ | |
public | √ | √ | √ | √ |
实际开发中,一般只用private和public
- 成员变量私有
- 方法公开
特例:如果方法中的代码是抽取其他方法中共性代码,这个方法一般也私有。
2、代码块
- 局部代码块
- 构造代码块
- 静态代码块
public class Text{ public static void main(String[ ] args){ { 代码块 int a = 10; System.out.pringtIn(a); } } } |
① 局部代码块
提前结束代码的生命周期
(已淘汰)
public class Text{ public static void main(String[ ] args){ { 局部代码块 int a = 10; System.out.pringtIn(a); } } } |
②构造代码块
1.写在成员位置的代码块
2.作用:可以把多个构造方法中重复的代码抽取出来 优先于构造方法执行
3.执行时机:我们在创建本类对象的时候会先执行构造代码块再执行构造方法
当多个构造方法有重复代码时,构造方法就淘汰了
弊端:创建一个对象重复一次空参
静态代码块 (重点)
现代代码块
格式:static{ }
特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发、只执行一次
使用场景:在类加载的时候,做一些数据的初始化的时候使用。
四、抽象类和抽象方法
①抽象方法
1、抽象方法:将共性的行为(方法)抽取到父类之后。由于每一个子类执行的内容是不一样,所以,在父类中不能确定具体的方法体。该方法就可以定义为抽象方法。
2、抽象类:如果一个类中存在抽象方法,那么该类就必须声明为抽象类
②⭐抽象类和抽象方法的定义格式
- 抽象方法的定义格式:
public abstract 返回值类型 方法名(参数列表);
- 抽象类的定义格式:
public abstract class 类名{ }
③抽象类和抽象方法的注意事项
- 抽象类不能实例化 抽象类不能创建对象
- 抽象类中不一定有抽象方法,有抽象方法的类一定是抽象类
- 可以有构造方法
- 抽象类的子类
要么重写抽象类中的所有抽象方法
要么是抽象类——还要有一个子类去重写
④练习——编写带有抽象类的标准Javabean类
青蛙frog 属性:名字,年龄 行为:吃虫子,喝水
狗Dog 属性:名字,年龄 行为:吃骨头,喝水
山羊Sheep 属性:名字,年龄 行为:吃草,喝水
Animal类
Dog类
Frog类
Sheep类
测试类