Eclipse中创建类时可快捷创建继承
关于Java语言当中的多态语法机制(概念)
/**
* 1、Animal,Cat,Bird三者之间关系
* Cat继承Animal
* Bird继承Animal
* Cat和Bird之间没有继承关系
*
* 2、面向对象三大特征:封装 继承 多态
*
* 3、关于多态中设计到的几个概念:
* *向上转型(upcasting)
* 子类型-->父类型 又称:自动类型转换。
*
* *向下转型(downcasting)
* 父类型-->子类型 又称:强制类型转换。【需要加强制类型转换符】
*
* *无论是向上转型还是向下转型,两种类型之间必须要有继承关系。
* 没有继承关系程序是无法编译通过的。
*/
以前编写的代码:
public static void main(String[] args) {
//以前编写的程序
Animal a1 = new Animal();
a1.move();
Cat c1 = new Cat();
c1.move();
c1.catchMouse();
Bird b1 = new Bird();
b1.move();
}
使用多态语法机制:
//使用多态语法机制
Animal a2 = new Cat();
/**
*
* 1、Animal和Cat之间存在继承关系,Animal是父类,Cat是子类
* 2、Cat is an Animal
* 3、new Cat(); 创建的类型是Cat, a2这个引用的数据类型是Animal,他们进行了类型转 换
* 子类型转换成父类型,称为向上转型
* 4、Java允许这种语法:父类型引用指向子类型对象。
*
*/
理解:
class 人 {
public void run(){
System.out.println("锻炼身体");
}
}
class 运动员 extends 人 {
public void run(){
System.out.println("比赛呢!");
}
}
main(){
人 李四 = new 人 ( );
李四.跑步 ( ); //锻炼身体
人 张三 = new 运动员 ( );
张三.跑步 ( ) ; //比赛呢!
}
因此对于以下这段代码:
a2.move(); //猫在走猫步
/**理解:
* 1、以上程序可以编译通过,编译器检查a2这个引用数据类型为Animal,由于在Animal字节码当中有move()方法,编译通过
* 这个过程称为静态绑定,编译阶段绑定。
* 2、在运行阶段当中,JVM堆内存当中真是创建的对象是Cat对象,那么以下程序在运行阶段一定会调用Cat对象的move()方法,
* 此时发生了程序的动态绑定,运行阶段绑定。
* 3、无论Cat类有没有写move方法,运行阶段一定调用的是Cat对象的move方法,因为底层真实的对象是Cat对象
*/
但以下代码编译错误
a2.catchMouse();
因为a2的类型为Animal类型(只有Cat类型中有catchMouse方法),从Animal字节码文件中查找catchMouse()方法,最终没有找到该方法
/**此时:
* 需求:
* 假设想让以上对象执行catchMouse()方法
* a2无法直接调用,因为a2的类型Animal中没有这个方法
* 我们可以将a2强制类型转换为Cat类型。
* a2的类型是Animal(父类),转换成Cat类型(子类),被称为向下转型/downcasting
*
* 注:向下转型也需要两种类型之间有继承关系。不然编译报错。强制类型转化需要加强制类型转换符
*
* 什么时候需要使用向下转型呢?
* 当调用的方法或访问的属性是子类型中特有的,在父类型当中不存在
*
*/实现:
Cat c2 = (Cat)a2;
c2.catchMouse();
其过程类似:
long x = 100L;
int i = (int)x;
Animal a3 = new Bird();
Cat c3 = (Cat)a3;
/**分析:
* 1、以上程序编译是没有问题的,因为编译器检测到a3引用的数据类型是Animal
* Animal和Cat之间存在继承关系,并且Animal是父类型,Cat是子类型,语法合格
* 2、程序在运行阶段出现异常,因为JVM堆内存中真实存在的对象是Bird类型,
* Bird对象无法转换成Cat对象,因为二者之间不存在继承关系,
* 此时出现著名异常: java.lang.ClassCastException类型转换异常
* 这种异常总是在“向下转型时”发生。
*/
/**
* 1、这种异常总是在“向下转型时”发生,也就是说“向下转型”存在隐患(编译过但运行错)。
* 2、向上转型只要编译通过运行不会出问题。Animal a2 = new Cat();
* 3、向下转型编译通过但运行可能会出问题。Animal a3 = new Bird(); Cat c3 = (Cat)a3;
* 4、怎么避免ClassCastException异常?
* 使用instanceof运算符可避免出现以上的异常
*
* 5、如何使用instanceof?
*
* 5.1语法格式:
* (引用 instanceof 数据类型名)
* 5.2以上运算符的执行结果类型是布尔类型,结果可能是true/false
*
* 5.3关于运算结果true/false:
* 假设:(a instanceof Animal)
* true表示: a这个引用指向的对象是Animal类型。
* false表示:a这个引用指向的对象不是Animal类型。
*
* 6、java规范中要求:在进行强制类型转换之前,建议采用instanceof运算符进行判读,避免ClassCastException异常的发生
* 这是一种编程的好习惯
*/
Animal a3 = new Bird();
//当a3引用指向地对象确实是一个Cat时
if(a3 instanceof Cat) {
Cat c3 = (Cat)a3;
c3.catchMouse();
}else if(a3 instanceof Bird) {
Bird b2 = (Bird)a3;
b2.move();
}
//结果:鸟儿在飞翔!
总结多态语法:
public static void main(String[] args) {
//父类型引用指向子类型
//向上转型
Animal a1 = new Cat();
Animal a2 = new Bird();
//向下转型【只要当访问子类对象当中特有的方法】
if(a1 instanceof Cat) {
Cat c1 = (Cat)a1;
}
if(a2 instanceof Bird) {
Bird b1 = (Bird)a2;
}
}
多态语法的作用
/**
* 多态在实际开发中的作用,以下以主人喂养宠物为例:
* 1、分析:主人喂养宠物这个场景的实现需要进行类型的抽象:
* -主人【类】
* -主人可以喂养宠物,所以主人有喂养的这个动作
* -宠物【类】
* -宠物可以吃东西,所以宠物有吃东西的这个动作
*
* 2、面向对象编程的核心:定义好类,然后将类实例化为对象,给一个环境驱使一下,让各个对象协作起来形成系统
*
* 3、多态的作用是什么?
* 降低程序的耦合度,提高程序的扩展力。
* 能使用多态尽量使用。
* 父类型引用指向子类型
*
* 【核心】:面向抽象编程,尽量不要面向具体编程。
*
*/
public class Cat {
public void eat() {
System.out.println("Cat is eating fish!");
}
}
public class Dog {
public void eat() {
System.out.println("Dog is eating meat!");
}
}
public class Master {
public void feed(Cat c) {
c.eat();
}
public void feed(Dog d) {
d.eat();
}
}
测试程序:
ublic class Test {
public static void main(String[] args) {
//创建主人对象
Master zhangsan = new Master();
//创建猫对象
Cat Tom = new Cat();
//主人喂养猫
zhangsan.feed(Tom);
//创建小狗对象
Dog Amy = new Dog();
//主人喂养小狗
zhangsan.feed(Amy);
}
}
/**
* 这种方式没有使用Java语言当中的多态机制,存在缺点:
* Master的扩展力很差
*/
修改,创建一个新的Pet宠物类(父类),并让其他子类继承父类(extends)
public class Pet {
//宠物都可以吃东西
public void eat() {
}
public class Cat extends Pet{
public void eat() {
System.out.println("Cat is eating fish!");
}
}
public class Dog extends Pet{
public void eat() {
System.out.println("Dog is eating meat!");
}
}
此时修改Master类,使程序耦合度变强
public class Master {
public void feed(Pet pet) {
pet.eat();
}
}
这样多态机制的使用使得未来在进行java软件开发时软件更新不必修改整个代码。