今天主要学习面向对象的其他两个特征,继承和多态,以及他们的具体应用
[修饰符列表] class 类名 extends 父类名{
类体
}
java语言当中的继承只支持单继承,一个类不能同时继承很多类,只能继承一个类。
虽然java语言当中只支持单继承,但是一个类也可以间接继承其他类,例如:
C extends B{
}
B extends A{
}
A extends T{
}
C直接继承B类,但是C类间接继承T、A类
java语言中假设一个类没有显示的继承任何类,该类默认继承JavaSE库当中提供的java.lang.Object类
java语言中任何一个类中都有Object类的特征
public class Account {
private String actno;
private double balance;
public Account(String actno, double balance) {
this.actno = actno;
this.balance = balance;
}
public Account() {
}
public String getActno() {
return actno;
}
public void setActno(String actno) {
this.actno = actno;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
}
public class CreditAccount extends Account {
private double credit;
public CreditAccount(String actno, double balance, double credit) {
this.credit = credit;
}
public CreditAccount() {
}
public double getCredit() {
return credit;
}
public void setCredit(double credit) {
this.credit = credit;
}
}
public class ExtendsTest {
public static void main(String[] args) {
CreditAccount act = new CreditAccount();
//本来CreditAccount类中没有set/get方法
act.setActno("act-001");
act.setBalance(-1000.0);
act.setCredit(0.99);
System.out.println(act.getActno()+","+act.getBalance()+","+act.getCredit());
}
}
//动物类
public class Animal {
public void move(){
System.out.println("动物在移动");
}
}
//猫类
public class Cat extends Animal {
//重写父类中继承过来的方法
public void move(){
System.out.println("猫在走猫步");
}
//不是从父类中继承过来的,是子类中特有的【不是所有动物都能抓老鼠】
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
public class Test {
public static void main(String[] args) {
//使用多态语法机制
Animal a2 = new Cat();
a2.move();//猫在走猫步
//以下程序为什么编译报错
/*
*因为编译阶段编译器检测到a2类型是Animal类型,从Animal.class字节码文件当中查找catchMouse()
*最终没有找到该方法,导致静态绑定失败,也就是编译失败
*/
//a2.catchMouse();
}
}
我们可以将a2强制类型转换为Cat类型。a2的类型是Animal(父类型),转换成Cat(子类型),被称为向下转型/强制类型转换,加强制类型转换符。
向下转型也必须要两种类型之间必须有继承关系,不然编译报错。
public class Bird extends Animal {
//重写父类中继承过来的方法
public void move(){
System.out.println("鸟儿在飞翔");
}
public void fly(){
System.out.println("Bird fly!");
}
}
public class Test {
public static void main(String[] args) {
//使用多态语法机制
Animal a2 = new Cat();
a2.move();//猫在走猫步
//以下程序为什么编译报错
/*
*因为编译阶段编译器检测到a2类型是Animal类型,从Animal.class字节码文件当中查找catchMouse()
*最终没有找到该方法,导致静态绑定失败,也就是编译失败
*/
//a2.catchMouse();
Cat c2 = (Cat)a2;
//父类型引用指向子类型对象【多态】
Animal a3 = new Bird();
/*
以下编译是没有问题的,因为编译器检查到a3数据类型是Aniaml
Animal和Cat之间存在继承关系,并且Animal是父类型,Cat是子类型
父类型转换成子类型叫做向下转型,语法合格
但是程序编译虽然通过,但是运行会出现异常,因为JVM堆内存当中真实存在的对象是Bird类型,Bird类型 无法转换成Cat类型,因为两种对象之间不存在任何继承关系,此时出现著名的异常:
java.lang.ClassCastException
类型转换异常,这种异常总是在“向下转型”的时候发生
*/
Cat c3 = (Cat)a3;
}
}
(引用 instanceof 数据类型名)
假设:(a instanceof Animal)
true表示:a这个引用指向的对象是一个Animal类型
false表示:a这个引用指向的对象不是一个Animal类型
上面的代码升级为【改动的地方在代码最后】
public class Test {
public static void main(String[] args) {
//使用多态语法机制
Animal a2 = new Cat();
a2.move();//猫在走猫步
//以下程序为什么编译报错
/*
*因为编译阶段编译器检测到a2类型是Animal类型,从Animal.class字节码文件当中查找catchMouse()
*最终没有找到该方法,导致静态绑定失败,也就是编译失败
*/
//a2.catchMouse();
Cat c2 = (Cat)a2;
//父类型引用指向子类型对象【多态】
Animal a3 = new Bird();
/*
以下编译是没有问题的,因为编译器检查到a3数据类型是Aniaml
Animal和Cat之间存在继承关系,并且Animal是父类型,Cat是子类型
父类型转换成子类型叫做向下转型,语法合格
但是程序编译虽然通过,但是运行会出现异常,因为JVM堆内存当中真实存在的对象是Bird类型,Bird类型 无法转换成Cat类型,因为两种对象之间不存在任何继承关系,此时出现著名的异常:
java.lang.ClassCastException
类型转换异常,这种异常总是在“向下转型”的时候发生
*/
//Cat c3 = (Cat)a3;
if(a3 instanceof Cat){
Cat c3 = (Cat)a3;
c3.catchMouse();
}else if(a3 instanceof Bird){
Bird b2 = (Bird)a3;
b2.fly();
}
}
java规范中要求:在进行强制类型转换之前,建议采用instanceof运算符进行判断,避免异常的发生