复习7:三大特性

三大特性

  • 封装
  • 继承
  • 多态

三大特性:封装

封装是什么

将成员变量私有化,并且提供对应的公共访问方法

封装的优点
  • 提高代码的复用性
  • 提高代码的可阅读性
  • 隐藏核心实现的逻辑代码,简化外部逻辑,并且阻止来自外部的随意访问
  • 实现代码与功能的一对一匹配
封装的实现

核心:

  • 成员变量私有化:private
  • 提供公共访问方法:getter/setter

注意:只有私有化后的成员变量才能叫做属性

示例:

package day20191103;

public class Demo01 {
	private int a;
	private int b;
	public void Demo01() {
		
	}
	public int getA() {
		return a;
	}
	public void setA(int a) {
		this.a = a;
	}
	public int getB() {
		return b;
	}
	public void setB(int b) {
		this.b = b;
	}
	
}
实体类的规范

实体类是什么:具有实际意义的类叫做实体类,又叫JavaBean

实体类有什么:

  • 属性
  • 无参构造器
  • getter/setter

JavaBean的规范

  • 命名规范:单个单词首字母大写,多个单词的组合遵循驼峰命名法
  • 成员变量私有化,提供getter/setter方法
  • 提供无参构造器
  • 重写equals()和hashCode()
  • 重写toString()

注意:业务代码不能写在实体类中


三大特性:继承

继承是什么

子类继承父类,子类拥有父类所有(公开的)成员属性和成员方法(构造器除外),同时子类也可以拥有自己特有的成员属性和成员方法

注意:

  • 若子类自己的成员属性与父类同名,则父类的成员属性被覆盖
  • 若子类自己的成员方法与父类同名,则发生方法重写
继承的作用
  • 提高代码的复用性
    • 提取公共特征
  • 可以在父类的基础上进行扩展
继承的使用

关键词:extends

示例:

class Animal{
    String name;
    int age;
    public void sleep(){
        
    }
    public void eat(){
        
    }
}
class People extends Animal{
    String bitthday;
    public void study(){
        
    }
}
public static void main(String[] args){
    People p = new People();
    p.study();
    //子类可以拥有父类的成员变量和成员方法
    p.sleep();
}
继承的特点
  • 继承具有传递性,即子类继承父类的同时,也会继承父类的父类(爷爷-爸爸-儿子)

  • 一个父类可以有多个子类(一个爸爸可以有多个儿子)

  • 一个子类只能有一个父类(一个儿子只能有一个爸爸)

  • 如果一个类没有继承任何类,那么这个类默认继承Object类,所以每个类都有父类(每个儿子必定有一个爸爸)

  • 结合第一点和第四点,我们可以得知:所有类都继承了Object类。这个继承可以分为两种:

    • 直接继承:子类直接继承Object类
    class Son extends Object{
        //直接继承
    }
    
    • 间接继承:子类的父类(或最高代)继承Object类
    class Father{
        
    }
    
    class Son extends Father{
        //子类继承父类,父类继承Object类
    }
    
子类内存在堆中的表现形式

子类内存在堆中分为两个部分

  • 父类对象
  • 子类对象

这两个对象在new操作时被创建,对象中有各自成员属性与成员方法。在调用成员属性和成员方法时,遵循就近原则:子类对象中存在同名的属性或方法时,则调用子类中的属性和方法;否则,就调用父类对象中的属性或方法(方法重写的原理)。

内存示意图如下:

子类内存

子类调用父类成员

关键字:super

super是什么

  • 表示父类对象,与this用法类似、意义不同

super的作用

  • 调用父类(公开的)构造器:super(参数列表)
  • 调用父类(公开的)成员属性:super.属性名()
  • 调用父类(公开的)成员方法:super.方法名()

super调用自身构造器的注意点

  • 只能放在构造器中
  • 必须是第一行代码

注意:

  • 每一个类的构造器中都有一个隐含的super(),可以被自定义的**super(参数)**覆盖
    • 在子类实例化对象时,一定会在构造自身之前先构造一个父类对象
    • 当父类只有有参构造器时,子类构造器将出现错误。因此,为了方便继承,每一个父类都必须添加无参构造器

三大特性:多态

多态

多态的表现形式

  • 重载
  • 重写

多态的前提条件

  • 具有继承关系的父、子类(实现抽象类也算)
方法重载

方法重载的条件

  • 同一个类中
  • 方法名相同、参数列表不同的方法构成重载
    1. 参数个数不同
    2. 参数个数相同,参数类型不同
    3. 参数个数相同,参数类型相同,相同类型的参数顺序不同

注意1:

  • 参数列表的异同判断与参数名称无关
  • 方法重载与返回值类型无关
  • 方法重载与访问控制符无关
  • 调用方法时,根据传入的参数确定调用哪一个重载方法

方法重载的作用

  • 提高代码的复用性
  • 提高代码的阅读性
  • 使代码更加规范
方法重写

方法重写的条件:

  • 在子类中(继承/抽象)
  • 返回值类型相同或是父类返回值类型的子类,方法名、参数列表必须相同
  • 访问控制权限不能比父类窄

方法重写的作用:

  • 提高代码的复用性
  • 体现不同对象之间的差异性

示例:

package day20191029;

public class Demo01 {
	public static void main(String[] args) {
		Son son = new Son();
		son.method();
	}
}
class Father{
	public Father( ) {
		
	}
	public void method() {
		System.out.println("我是父类方法");
	}
}
class Son extends Father{
	public Son() {
		
	}
	public void method() {
		System.out.println("我是子类方法");
	}
}

注意:子类调用方法时,遵循就近原则

向上造型

向上造型是什么:父类类型的引用变量接收子类类型的对象,是多态的体现

  • 示例:Father father = new Son();

向上造型中的相关概念

  • 编译时类型:编译时,编译器眼中的变量类型(Father father部分)
  • 运行时类型:运行时,虚拟机眼中的变量类型(**new Son()**部分 )

编译器认为father的类型是Father,但是在运行时,虚拟机认为father的类型是Son

向上造型中的多态体现

  • 编译时类型决定对象能调用哪些方法:通俗地说,father能"."出Father中的所有方法
  • 运行时类型决定对象调用的方法内容:如果father调用的方法在Son中被重写,则调用Son中的方法;否则,调用Father中的方法
  • 示例:
package day20191029;

public class Demo01 {
	public static void main(String[] args) {
		Father father = new Son();
		father.method();//method()在子类中被重写,所以此时调用的是子类中的方法
	}
}
class Father{
	public Father( ) {
		
	}
	public void method() {
		System.out.println("我是父类方法");
	}
}
class Son extends Father{
	public Son() {
		
	}
	public void method() {
		System.out.println("我是子类方法");
	}
}

注意:只有调用被重写的方法才能体现多态,如果调用未被重写的方法,则无法体现多态

向上造型的类型转换

转换的条件

  • 必须有直接继承关系
  • 运行时类型相同或子类转换成父类

父类不能转换成子类,而子类能转换成父类的原因:子类中除了继承自父类的成员属性和成员方法,还有属于自己的属性和方法。父类转换成子类时,引用变量的编译时类型变成了子类类型,而运行时类型依然是父类类型,由于编译时类型的特性,转换后的引用变量能使用子类特有的属性和方法,但是实际运行时父类中并没有这些属性和方法,于是发生了报错;而子类转换成父类就没有这个问题,因为子类有父类所有(公开的)成员属性和成员方法。

示例:

package day20191029;

public class Demo01 {
	public static void main(String[] args) {
		
		Father father1 = new Son();
		Son son1 = (Son)father1;
		son1.method();
		
		Son son2 = new Son();
		Father father2 = (Father)son2;
		
        //编译通过,但是运行后抛出ClassCastException
		Father father = new Father();
		Son son3 = (Son)father;
		son3.method2();
	}
}

class Father{
	public Father( ) {
		
	}
	public void method() {
		System.out.println("我是父类方法1");
	}
	public void method2() {
		System.out.println("我是父类方法2");
	}
}

class Son extends Father{
	public Son() {
		
	}
	public void method() {
		System.out.println("我是子类方法1");
	}
}

注意:强制类型转换属于编译时语法,该语法只在编译时有效,运行时取决于运行时类型。因此才会发生编译通过,但是运行报错。

亲子鉴定

关键字:instanceof

  • 作用:判断一个引用变量是否属于某个类型(取决于运行时类型),返回值是布尔类型
  • 使用示例:father instanceof Father

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章