1.继承
当多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可。
继承的好处:
- 代码的复用
- 代码的扩展
- 让类与类之间产生了关系,可以创建更为特殊的类型。
继承的弊端:
- 类的耦合性增强了。
- 开发的原则:高内聚,低耦合。
- 耦合:类与类的关系
- 内聚:就是自己完成某件事情的能力
继承的语法格式:
【修饰符】 class 子类 extends 父类{
}
继承的特点:
- 子类会继承父类的所有的非私有的属性和方法
- 子类不会继承父类的构造器,因为父类的构造器是用于创建父类的对象的
- 子类的构造器中又必须去调用父类的构造器
在创建子类对象的同时,为从父类继承的属性进行初始化用,可以借助父类的构造器中的代码为属性赋值。 - Java只支持单继承,不允许多重继承,但是Java支持多层继承
- 一个子类只能有一个“直接”父类
- 父类还可以有父类
- 一个父类可以同时拥有很多个子类
1.1关键字super
super:父类的
用法:
- super.属性
当子类声明了和父类同名的成员变量时,那么如果要表示某个成员变量是父类的,那么可以加“super.”
- super.方法
当子类重写了父类的方法,又需要在子类中调用父类被重写的方法,可以使用"super."
- super()或super(实参列表)
super():表示调用父类的无参构造
super(实参列表):表示调用父类的有参构造
注意:
(1)如果要写super()或super(实参列表),必须写在子类构造器的首行
(2)如果子类的构造器中没有写:super()或super(实参列表),那么默认会有 super()
(3)如果父类没有无参构造,那么在子类的构造器的首行“必须”写super(实参列表)
(4)super的追溯不仅限于直接父类
this与super的区别:
区别点 | this | super |
访问属性 | 访问本类的属性,如果本类没有此属性则从父类中继续查找 | 直接访问父类中的属性 |
调用方法 | 访问本类中的方法,如果本类没有此方法,则从父类中找 | 直接访问父类中的方法 |
调用构造器 | 调用本类构造器,必须放在构造器的首行 | 调用父类构造器,必须放在子类构造器首行 |
代表 | 表示当前对象 | 表示父类的 |
注意:
- 如果某个属性或方法前面使用“this.”,那么先从本类中查找,如果未找到,会沿着父类查找
- 如果某个属性或方法前面使用“super.”,那么先从直接父类中查找,如果未找到,会沿着继承关系往上找
- 如果某个属性或方法前面既没有“this.”,也没有“super.”,遵循就近原则,开始找
1.2方法的重写
方法的重写(Override):
当子类继承了父类的方法时,又觉得父类的方法体的实现不适合于子类,那么子类可以选择进行重写。
方法的重写的要求:
- 方法名:必须相同
- 形参列表:必须相同
- 修饰符
权限修饰符: >=
- 返回值类型
如果是基本数据类型和void:必须相同
如果是引用数据类型:<=
注意:重写的方法不能是static的,final的,子类不可见的
重载(Overload)与重写(Override)的区别
重载 | 重写 | |
位置 | 同一个类中 | 在父子类中 |
方法名 | 必须相同 | 必须相同 |
形参列表 | 必须不同 | 必须相同 |
返回值类型 | 无关 | void和基本数据类型必须一致,引用数据类型<= |
权限修饰符 | 无关(建议一致) | 重写方法的权限修饰符要么和被重写方法一样,要么比被重写方法的权限范围大 |
2.final关键字
final:最终的
用法:
(1)修饰类(包括外部类、内部类)
表示这个类不能被继承,没有子类
提高安全性,提高程序的可读性。
(2)修饰方法
表示这个方法不能被重写
(3)修饰变量(成员变量(类变量、实例变量),局部变量)
即称为常量 ,表示这个变量的值不能被修改
(4)修饰引用数据类型,表示地址值不能修改。
注意:如果某个成员变量用final修饰后,也得手动赋值,而且这个值一旦赋完,就不能修改了,即没有set方法。
3.多态
多态:一类事物的多种表现形态。
在Java中
(1)重载:在一个类中一个方法功能的多种表现形态
重写:父子类对于同一个方法表现出不同的形式
(2)对象的多态性:若编译时类型和运行时类型不一致,就出现多态(Polymorphism)
父类的引用指向子类的对象
语法格式:
父类 引用/变量 = 子类的对象;
多态前提:
- 继承
- 方法的重写
- 父类型引用指向子类型对象
现象:
- 成员变量:不具备多态性,只看引用变量所属的类。
- 多态的形式调用方法:编译时看左边/“父类”,运行时看右边/“子类”。
编译时,因为按父类编译,那么只能父类有的方法,子类扩展的方法是无法调用的;
执行时一定是运行子类重写的过的方法体。
代码示例:
class Person{
public void eat(){
System.out.println("吃饭");
}
public void walk(){
System.out.println("走路");
}
}
class Woman extends Person{
public void eat(){
System.out.println("细嚼慢咽的吃饭");
}
public void walk(){
System.out.println("婀娜多姿走路");
}
public void shop(){
System.out.println("买买买...");
}
}
class Man extends Person{
public void eat(){
System.out.println("狼吞虎咽的吃饭");
}
public void walk(){
System.out.println("大摇大摆的走路");
}
public void smoke(){
System.out.println("吞云吐雾");
}
}
class Test{
public static void main(String[] args){
Person p = new Woman();//多态引用
p.eat();//执行子类重写
p.walk();//执行子类重写
//p.shop();//无法调用
}
}
3.1多态的应用
(1)多态参数:形参是父类,实参是子类对象
示例代码:
class Test{
public static void main(String[] args){
test(new Woman());//实参是子类对象
test(new Man());//实参是子类对象
}
public static void test(Person p){//形参是父类类型
p.eat();
p.walk();
}
}
(2)多态数组:数组元素类型是父类,元素存储的是子类对象
示例代码:多态数组
class Test{
public static void main(String[] args){
Person[] arr = new Person[2];//多态数组
arr[0] = new Woman();
arr[1] = new Man();
for(int i=0; i<arr.length; i++){
all[i].eat();
all[i].walk();
}
}
}
3.2向上转型和向下转型
(1)向上转型:自动类型转换
当把子类的对象赋值给父类的变量时(即多态引用时),在编译时,这个对象就向上转型为父类。此时就看不见子类“特有、扩展”的方法。
(2)向下转型:强制转换。有风险,当类型不兼容的情况下进行转型会出现ClassCastException异常。为了避免该异常的发生,建议进行向下转型之前进行运行期类型判断,即下面提到的instanceof。
当需要把父类的变量赋值给一个子类的变量时,就需要向下转型。
要想转型成功,必须保证该变量中保存的对象的运行时类型是<=强转的类型
示例代码:
class Person{
//方法代码省略...
}
class Woman extends Person{
//方法代码省略...
}
class ChineseWoman extends Woman{
//方法代码省略...
}
public class Test{
public static void main(String[] args){
//向上转型
Person p1 = new Woman();
//向下转型
Woman m = (Woman)p1;
//p1变量中实际存储的对象就是Woman类型,和强转的Woman类型一样
//向上转型
Person p2 = new ChineseWoman();
//向下转型
Woman w2 = (Woman) p2;
//p2变量中实际存储的对象是ChineseWoman类型,强制的类型是Woman,ChineseWoman<Woman类型
}
}
(3)instanceof
表达式语法格式:
对象/变量 instanceof 类型
运算结果:true 或 false
作用:
用来判断这个对象是否属于这个类型,或者说,是否是这个类型的对象或这个类型子类的对象。在java程序开发中,进行任何向下转型操作前,必须使用instanceof进行判断,要养成这样的编程习惯。
示例代码:
class Person{
//方法代码省略...
}
class Woman extends Person{
//方法代码省略...
}
class ChineseWoman extends Woman{
//方法代码省略...
}
public class Test{
public static void main(String[] args){
Person p = new Person();
Woman w = new Woman();
ChineseWoman c = new ChineseWoman();
if(p instanceof Woman){//false
}
if(w instanceof Woman){//true
}
if(c instanceof Woman){//true
}
}
}