内容
1.static
2.继承
3.重写
4.多态
一.static
其实static在Java中和在c/c++中性质基本是一样的,这里就不再赘述
静态代码块
Java有静态代码块,格式是
static{
Java语句
}
注意:
①静态代码块在类加载时执行,并且只执行一次.
②在一个类中可以编写多个。当需要某些程序在类加载时刻执行时,要想到可以使用静态代码块。
③大多数“工具类”中的方法都是静态方法
因为工具类就是方便编程,为了方便方法的调用,自然不需要new对象是最好的
小提示:Java可以有多个main方法,它们之间构成重载关系
二.继承
Java继承的基本作用是:代码复用。但是继承更重要的作用是:有了继承才有了以后“方法的覆盖”和“多态机制”
继承语法格式
[修饰符列表] class 类名 extends 父类名{
}
注意:①Java只支持单继承,但是可以间接继承多个。
②父类也叫超类 superclass,子类也叫subclass。
③Java语言中任何一个类都有Object类的特征,也就是说都默认继承Object
三.重写
Java里面重写和c++基本是一样的
何时使用方法重写?
当父类中的方法已经无法满足当前子类的需求,子类有必要将父类中继承过来的方法进行重新编写,这个重新编写的过程称为方法重写/方法覆盖
注意
①方法重写发生在具有继承关系的父子类之间,返回值类型不一定相同,方法名相同,形参列表相同
②访问权限不能更低,只能更高。
③抛出异常不能更多,可以更少【后面会学】
④私有方法和构造方法不能继承,自然也不能覆盖。
⑤静态方法不存在覆盖
四.多态
在c++中也学过多态,当时是这么说的
其实当时没有学好,现在觉得Java和c++的多态有很多地方都是相同的,所以在这里的Java学习中要掌握好多态了
1.多态中涉及的几个概念
①向上转型(upcasting)
子类型——》父类型
又被称为:自动类型转换
(其实这个就相当于c++中的父类的指针调用子类的函数)
②向下转型(downcasting)
父类型——》子类型
又被称为:强制类型转换【需要加强制类型转换符】
注意:无论是向上转型还是向下转型,两种类型之间必须要有继承关系
2.使用示例分析
(1)父类型引用指向子类型对象
例题:Cat继承Animal
Animal a2 = new Cat();
看似难懂,但其实可以理解为,猫是动物
这里是子类型转换成父类型,是向上转型,也是自动类型转换。
图形表示如下
分析
①.Java程序永远都分为编译阶段和运行阶段
②.先分析编译阶段,再分析运行阶段。编译无法通过,根本是无法运行的
③.在这个例子中,编译阶段编译器检查a2这个引用的数据类型为Animal,由于Animal.class字节码中有move()方法,所以编译通过了,这个过程我们称为静态绑定/编译阶段绑定。只有静态绑定成功之后才有后续的运行
④.在程序运行阶段,JVM堆内存当中真实创建的对象是Cat对象,那么以下程序在运行阶段一定会调用Cat对象的move()方法,而不是Animal对象的move(),此时发生了程序的动态绑定/运行阶段绑定
a2.move();
假如还有一句是
a2.catchMouse();
分析
也不行。
因为catchMouse()是Cat这个类特有的,而a2是Animal类,里面没有catchMouse()这个方法,编译阶段就不会通过,更别谈运行了。
⑤.这个和重写无关,就直接在Cat对象中找move()方法。无论Cat类有没有重写move方法,运行阶段一定调用的是Cat对象的move()方法,因为底层的真实对象就是Cat对象
⑥.父类型引用指向子类型对象这种机制导致程序存在编译阶段绑定和运行阶段绑定两种不同的形态/状态。这种机制可以称为一种多态语法机制
(2)假如想让a2执行catchMouse()?也就是运行子类独有的方法?
可以将a2强转为Cat类型(这个时候编译器就自己认为是调用的Cat自己的catchMouse()
父类转换为子类,被称为向下转型,也是强制类型转换,需要加强制类型转换符
何时需要?
当调用的方法是子类中特有的,在父类当中不存在,
必须进行向下转型(也就是让编译器觉得你是个猫才行)
Cat c2 = (Cat)a2;
(3)java.lang.ClassCastException异常
Animal a3 = new Bird();
Cat c3 = (Cat)a3;
分析
上面的程序编译是没有问题的,因为编译器检查到a3的数据类型是Animal,Animal和Cat之间存在继承关系,这种叫做向下转型,语法合格
但是,虽然编译通过,但是在运行阶段会出现异常,因为JVM堆内存当中真实存在的是Bird类型,Bird对象无法转换成Cat对象,因为两种类型之间不存在任何继承关系,此时出现了著名的异常
java.lang.ClassCastException,即类型转换异常,这种异常总是在“向下转型”的时候会发生
3.instanceof
1.向上转型只要编译通过,运行一定不会出问题:如Animal a = new Cat();
2.向下转型编译通过,运行可能错误:如Animal a3 = new Bird(); Cat c3 = (Cat)a3;
3.如何避免向下转型这里出现的错误呢?
使用instanceof运算符
①语法格式
(引用 instanceof 数据类型名)
②执行结果
是布尔类型 true/false
假如有一段(a instanceof Animal)
true表示
a这个引用指向的对象是一个Animal类型(这个是看底层实际的指向,而不是表面的编译器以为的指向)
false表示
a这个引用指向的对象不是一个Animal类型
③使用示例
if(a3 instanceof Cat){
Cat c3 = (Cat)a3;
c3.catchMouse();
}else if(a3 instanceof Bird){
Bird b2 = (Bird)a3;
b2.fly();
}
在这里就会执行后面的elseif,因为a3就是属于鸟类,然后才可以调用子类中(在这里是鸟类)中特有的方法
4.多态在实际开发中的作用
降低程序的耦合度(关联度),提高程序的扩展力。
所以能使用多态就尽量使用多态。
多态使用一般是父类型引用指向子类型对象。和c++类似
核心:面向抽象编程,尽量不要面向具体编程