1、概述:表示同一个事物在不同情况下表现出不同的行为
- 多态性:指父类的某个方法被其子类重写时,可以各自产生自己的功能行为
2、使用多态的前提:要有继承或实现关系(接口);要有父类引用指向子类对象;要有方法的重写
3、多态的好处与弊端
| 好处 | 弊端 |
|---|---|
| 提高了程序的扩展性,用父类型作为参数,通过具体的子类性进行相关行为的操作 | 不能使用子类的特有成员 |
- 使用多态技术的核心技术之一:使用上转型对象
两种转型:
| 上转型 | 下转型 |
|---|---|
| 父类型 对象名=new子类型(); | 子类型 对象名=(子类型)父类引用; |
| 成员变量 | 成员方法 |
|---|---|
| 编译和运行均看父类 | 编译看父类,运行看子类 |
代码:
父类:
public class Animal {
int age=20;
public void eat(){
System.out.println("动物吃东西");
}
}
Cat:
public class Cat extends Animal{
int age=10;
int weight=20;
public void eat(){
System.out.println("猫吃鱼");
}
public void play(){
System.out.println("躲猫猫");
}
}
主类:
public class AnimalTest {
public static void main(String[] args) {
Animal c = new Cat();
System.out.println(c.age);//输出的是父类中定义的成员变量
//System.out.println(c.weight); 不能访问子类新定义的成员
c.eat();
//c.play(); 不能访问子类新定义的方法
}
}
(三)案例
用多态实现猫和狗
代码:
public class Animal {
private String name;
private int age;
public Animal(){
}
public Animal(String name,int age){
this.name=name;
this.age=age;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
public void eat(){
System.out.println("动物吃东西");
}
}
public class Cat extends Animal{
public Cat(){
}
public Cat(String name,int age){
super(name, age);//子类不继承父类的构造方法,直接使用父类的构造方法
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public class Dog extends Animal{
public Dog(){
}
public Dog(String name,int age){
super(name, age);
}
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
public class AnimalTest {
public static void main(String[] args) {
Animal a = new Cat();
a.setName("加菲");
a.setAge(5);
System.out.println(a.getName()+","+a.getAge());
a.eat();
a=new Dog();
a.setName("拉布拉多");
a.setAge(2);
System.out.println(a.getName()+","+a.getAge());
a.eat();
}
}
二、抽象类
1、抽象类的概述
- 是一种行为规范,是包含了子类所有的共性功能,其定义的方法在父类中没有具体体现。实现这一具体的细节在非抽象子类的方法重写中展示,也是多态的一种体现
2、抽象类的特点 - 格式(抽象类和抽象方法都要遵守):
- public abstract class 类名{} //抽象类的定义
- public abstract void eat();//抽象方法的定义
- abstract类中可以没有abstract方法,但含有abstract方法的一定是abstract类。
- 抽象类不能实例化,抽象类多态:要参照多态的方式把子类对象实例化
- 抽象类的子类:
| 可以重写抽象类中的所有方法 | 也可以直接拥有抽象类中的方法 |
|---|---|
| 通过非抽象子类的重写 | 子类是抽象类 |
- (Java实例化就是使用new关键字创建一个对象的过程)
3、抽象类的成员特点 - 对于abstract方法,只允许声明,没有方法体
- 不能使用final和abstract同时修饰一个方法,也不可以用static修饰abstract方法(即其方法必须是实例方法)
- 成员变量:既可以是变量,也可以是常量
- 成员方法:既可以是抽象方法,也可以是普通方法
- 构造方法:既可以是空参构造方法,也可以是有参构造方法
4、案例
同上面案例,只需将父类中的public void eat()方法改为public abstract void eat(){}即可。
1、概述:是一种公共的规范标准,只要符合均可以使用。更多的体现在对行为的抽象。接口属于引用型变量,接口变量可以存放该接口的类的实例的引用。
- 用interface来定义一个,接口,分为接口声明和接口体
-
格式:
- public interface 接口名{}
- 子类实现接口用implements
-
格式:
- public class 类名 implements 接口名{}
2、接口体中只有抽象方法,没有普通方法
3、接口体中所有的常量的访问权限一定都是public,而且是static常量。
-
特点
- 允许省略public、final、static修饰符
- (public static final) int num=30; 等价于 int num=30;
4、接口体中,所有的抽象方法的访问权限一定**都是public。
-
特点
- 允许省略修饰符public abstract修饰符
- public abstract int f() 等价于 int f()
5、接口实现类如果没有直接父类,则继承Object类,如下:
- public class IT extends Object implements Inter
等价于 public class IT implements Inter - 若此时在子类中有构造方法public IT(){ super(); },此时调用的是Object里的无参构造方法
6、接口回调=上转型(接口回调:实现接口的类的对象的引用赋值给接口变量,接口变量可以调用被该类实现的接口方法)
7、接口的思想:可以要求某些类有相同名称的方法,但方法的具体内容可以不同
8、接口抽象出重要的行为标准,该行为标准用抽象方法来表示
9、接口参数
| 数据类型 | 引用类型 |
|---|---|
| 若该参数类型是double类型,则可以向改参数传递byte、int、long、float、和double类型数据,即传递低于或等于该类型的数据 | 任何实现该接口的类的实例的引用传递给该接口参数 |
1、成员变量
- 只能是常量,默认修饰符:public abstract final
2、构造方法
- 没有,因为接口主要是实现扩展功能的,而没有具体存在
3、成员方法
- 只是是抽象方法
- 默认修饰符:public abstract
| 类和类 | 继承关系,只能单继承,但可以多层继承 |
|---|---|
| 类和接口 | 实现关系,可以单实现,也可以多实现。还可以在继承一个类的同时实现多个接口 |
| 接口和接口 | 继承关系,可以单继承,也可以多继承 |
1、从语法层面:
| 抽象类 | 接口 |
|---|---|
| 将抽象方法的实现交给其子类 | 将抽象方法的实现交给接口的类 |
| 变量、常量 | 常量 |
| 构造方法、抽象方法、非抽象方法 | 抽象方法 |
2、从设计层面
| 抽象类 | 接口 |
|---|---|
| 对类抽象,包括属性和行为 | 对行为抽象,主要是行为 |
| 是对事物的抽象 | 是对行为的抽象 |
| 是物体都具备的功能(一定能实现的) | 是有实现物体与物体间区别的功能(不一定有) |
例如:小A和小B都会唱歌(抽象),但他们两个人会不同的语言(接口),小A会法语,小B会拉丁语
3、形参与返回值
| 抽象类 | 接口 |
|---|---|
| 都是其子类对象 | 都是接口的实现类对象 |
4、与多态
| 继承 | 接口 |
|---|---|
| 要参照多态的方式把子类对象实例化,指父类的某个方法被其子类重写时,可以各自产生自己的功能行为 | 指不同的类在实现同一个接口时可能具有不同的实现方式,那么接口变量在回调接口方法时就可能具有多种形态 |
猫和狗:
public interface Jumpping {
public abstract void jump();
}
public abstract class Animal {
private String name;
private int age;
public Animal(){
}
public Animal(String name,int age){
this.name=name;
this.age=age;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
public abstract void eat();
}
public class Cat extends Animal implements Jumpping{
public Cat(){
}
public Cat(String name,int age){
super(name, age);//子类不继承父类的构造方法,直接使用父类的构造方法
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void jump() {
System.out.println("猫可以调高");
}
}
public class AnimalTest {
public static void main(String[] args) {
Jumpping j = new Cat();
j.jump();
System.out.println("------------");
Animal a = new Cat();
a.setName("加菲");
a.setAge(5);
a.eat();
//a.jump(); 上转不可以用实现接口的方法
System.out.println(a.getName()+","+a.getAge());
System.out.println("------------");
Cat c = new Cat();
c.setName("加菲猫");
c.setAge(2);
c.eat();
//c.Jump();
System.out.println(c.getName()+","+c.getAge());
}
}
四、异常
(一)概述
1、概述:异常就是程序出现了不正常的情况
2、结构体系:Error:严重问题,不需要处理
Exception:称为异常类,它表示程序本身可以处理的问题
- RuntimeException:在编译期间不检查,出现问题后,需要我们回来修改代码
- 非RuntimeException:编译期间必须处理的,否则程序不能通过编译,就更不能正常运行
3、JVM默认处理异常的两种方式
如果出现问题没有做出相应处理:
- 程序停止进行
- 把异常的名称、错误的原因及异常出现的位置等信息输出在控制台
1、格式
- try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}
2、执行流程 - 程序从try里面的代码开始执行
- 出现异常后,就会跳转到相应位置的catch里面执行
- 执行完毕后,程序还可以继续往下执行
- 代码样例如下:
public class TextDome {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method(){
try{
int[] arr = {1,2,3};
System.out.println(arr[3]);
System.out.println("这里能够访问到吗");
}catch(ArrayIndexOutOfBoundsException e) {
System.out.println("你访问的数组索引不存在,请回去修改为正确的索引");
e.printStackTrace();
}
}
}
(三)Throwable
1、throwable是Java语言中所有错误和异常的超类
- 只有作为此类(或其一个子类)的实例对象由Java虚拟机抛出,或由Java的throw语句抛出
- 只有该类/其子类可以是catch子句中的参数类型
- 常用的成员方法:
| 方法名 | 说明 |
|---|---|
| public String getMessage() | 返回此throwable的详细消息字符串 |
| public String toString() | 返回此可抛出的简短描述 |
| public void printStackTrace() | 把异常的错误信息输出在控制台(最全) |
2、代码
public class ExceptionDemo02 {
public static void main(String[] args) {
System.out.println("开始");
method();
System.out.println("结束");
}
public static void method() {
try {
int[] arr = {1, 2, 3};
System.out.println(arr[3]); //new ArrayIndexOutOfBoundsException();
// System.out.println("这里能够访问到吗");
// } catch (ArrayIndexOutOfBoundsException e)
// { //new ArrayIndexOutOfBoundsException();
// e.printStackTrace();
// public String getMessage():返回此 throwable 的详细消息字符串
// System.out.println(e.getMessage());
// Index 3 out of bounds for length 3
// public String toString():返回此可抛出的简短描述
// System.out.println(e.toString());
// java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
// public void printStackTrace():把异常的错误信息输出在控制台 e.printStackTrace();
// java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3
// at com.itheima_02.ExceptionDemo02.method(ExceptionDemo02.java:18)
// at com.itheima_02.ExceptionDemo02.main(ExceptionDemo02.java:11)
// }
}
}
(四)异常处理
当程序出现问题,需要自己来处理,有两种方案
- 第一种:try-catch(真正的处理由它实现)
- 第二种:throws
- 不是所有问题都有权限去处理,当无法处理的时候,用throws抛出
- 格式: throws 异常类名;(是跟在方法的括号后面)
- 不是真正的处理,只是把程序里的异常抛出去了
- 执行throw后==不可以继续执行了
1、两种异常的区别
| 编译时异常 | 运行时异常 |
|---|---|
| 都是Exception类及其子类 | 都是RuntimeException类及其子类 |
| 必须显示处理,否则程序就会发生错误,无法通过编译 | 无需显示处理,也可以和编译时异常一样处理(但出现问题后,需要返回原代码进行修改) |
| 有两种处理方案:try-catch、throws,若用后者,以后谁调用谁来处理 |
2、自定义异常
采用继承Exception来实现自定义
- 格式:public class 异常类名 extends Exception{
无参构造;
有参构造;
}
| throws | throw |
|---|---|
| 用在方法声明后,跟的是异常类名 | 用在方法体内,跟的是**异常对象名 |
| 表示抛出异常,由该方法的调用者来处理 | 表示抛出异常,由方法体内的语句处理 |
| 表示出现异常的一种可能性,并不一定会发生这些异常 | 执行throw一定出现了某种抛出异常 |



