08-Java继承、多态、super关键字、final关键字

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
             
         }
     }
 }

猜你喜欢

转载自blog.csdn.net/m0_46988935/article/details/110198397