2.面向对象的核心概念

文章目录

      • 1.重载和重写
        • 1.1 重载
        • 1.2 重写
        • 1.3 重载和重写
      • 2.多态
        • 2.1 什么是多态
          • 2.1.1 特设多态
          • 2.1.2 参数多态
          • 2.1.3 子类型
        • 2.2 Java中的多态
      • 3.继承与实现
      • 4.组合与继承
        • 4.1 继承复用
        • 4.2 组合复用
        • 4.3 组合和继承的区别和联系
        • 4.4 优缺点对比
        • 4.5 如何选择?
      • 5.构造函数
      • 6.变量

1.重载和重写

1.1 重载

  • 重载:在同一个类中,多个函数或者方法有同样的名称,但是参数列表不同。
    • 这样的同名不同参数的函数或者方法,互相称之为重载函数或者重载方法。

重载方法

/**
 * 狗
 */
public class Dog {

    public void bark() {
        System.out.println("woof");
    }

    // 重载方法
    public void bark(int num) {
        for (int i = 0; i < num; i++) {
            System.out.println("woof");
        }
    }
}
  • Dog类定义了两个bark方法,一个是没有参数的bark方法,另一个是包含一个int类型参数的bark方法。
    • 这两个方法就是重载方法,因为它们的方法名相同、参数列表不同
  • 编译期,编译器可以根据方法签名(方法名和参数)确定具体哪个bark方法被调用。
  • 方法重载满足条件
    • 被重载的方法:必须改变参数列表
    • 被重载的方法:可以改变返回类型
    • 被重载的方法:可以改变访问修饰符
    • 被重载的方法:可以声明新的或更广的检查异常
    • 方法能够在同一个类中或者一个子类中被重载

1.2 重写

  • 重写:在Java的子类与父类中,有两个名称和参数列表都相同的方法,由于它们具有相同的方法签名,所以子类中的新方法将覆盖父类中原有的方法。

重写方法

class Dog {
    public void bark() {
        System.out.println("woof");
    }
}

class Hound extends Dog1 {
    public void sniff() {
        System.out.println("sniff");
    }

    @Override
    public void bark() {
        System.out.println("bow1");
    }
}

/**
 * @description: 重写方法
 */
public class OverridingTest {
    public static void main(String[] args) {
        Dog dog = new Hound();
        dog.bark();
    }
}

输出结果

bow1
  • 分别在父类、子类中都定义了bark方法,并且它们都是无参方法,这种情况就是方法重写。

    • 即子类Hound重写了父类Dog中的bark方法。
  • 编译期:编译器会检查Dog类中是否有可访问的bark()方法,只要其中包含bark()方法,那么就可以编译通过。

  • 运行期Hound对象被new出来,并赋值给dog变量,这时,JVM明确地知道dog变量指向的是Hound对象的引用。

    • 所以,当dog调用bark()方法时,就会调用Hound类中定义的bark()方法。这就是所谓的动态多态性。
  • 方法重写满足条件

    • 参数列表必须完全与被重写方法的参数列表相同
    • 返回类型必须完全与被重写方法的返回类型相同
    • 访问级别的限制性一定不能比被重写方法的限制性强
    • 访问级别的限制性可以比被重写方法的限制性弱
    • 重写方法一定不能抛出新的检查异常或比被重写的方法声明的检查异常有更广泛的检查异常
    • 重写的方法能够抛出更少或更有限的异常
    • 不能重写被标记为final的方法
    • 如果不能继承一个方法,则不能重写这个方法

1.3 重载和重写

  • 重载是一个编译期概念,重写是一个运行期概念。
  • 重载遵循所谓编译期绑定,即在编译时根据参数变量的类型判断应该调用哪个方法。
  • 重写遵循所谓运行期绑定,即在程序运行时,根据引用变量所指向的实际对象的类型来调用方法。
  • Java中的方法重写是Java多态(子类型)的实现方式,而Java中的方法重载是特设多态的一种实现方式。

2.多态

2.1 什么是多态

  • 多态(Polymorphism):为不同数据类型的实体提供统一的接口,或者使用一个单一的符号来表使多种不同的类型。
2.1.1 特设多态
  • 特设多态是程序设计语言的一种多态,多态函数有多个不同的实现,依赖于其实参而调用相应版本的函数。

    • 函数重载运算符重载
  • 也叫静态多态:需要在编译期决定具体调用哪个方法。

2.1.2 参数多态
  • 参数多态是指声明与定义函数、复合类型、变量时不指定其具体的类型,而系统依据对象的所属类型,触发对应类别的方法,产生不同的行为。
    • Java中泛型函数式编程
2.1.3 子类型
  • 子类型多态:在面向对象程序设计中,当计算机程序运行时,相同的消息可能会发送给多个不同类别的对象,而系统依据对象的所属类别,触发对应类别的方法,产生不同的行为。

2.2 Java中的多态

  • 多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。
  • Java中的多态其实是一种运行期的状态。为了实现动态绑定,需要满足三个条件:
    • 有类继承或者接口实现
    • 子类要重写父类的方法
    • 父类的引用指向子类的对象

多态

/**
 * 父类
 */
public class Parent {
    public void call() {
        System.out.println("im Parent");
    }
}

/**
 * 子类1
 */
public class Son extends Parent{
    @Override
    public void call() {
        System.out.println("im Son");
    }
}

/**
 * 子类2
 */
public class Daughter extends Parent {
    @Override
    public void call() {
        System.out.println("im Daughter");
    }
}

/**
 * 多态测试
 */
public class Test {
    public static void main(String[] args) {
        Parent p = new Son();
        p.call();
        Parent p1 = new Daughter();
        p1.call();
    }
}

输出结果

im Son
im Daughter

3.继承与实现

  • 继承(Inheritance)

    • 如果多个类的某个部分的功能相同,那么可以抽象出一个类,把它们的相同部分都放到父类里,让它们都继承这个类。
    • 一个类(称为子类、子接口)继承另外的一个类(称为父类、父接口)的功能,并可以增加它自己的新功能的能力。
    • 根本原因:复用
    • 关键字:extends
    • 定义:属性方法、变量和常量
  • 组合(Implement)

    • 如果多个类处理的目标是一样的,但是处理的方法、方式不同,那么就定义一个接口,也就是一个标准,让它们都实现这个接口,各自实现自己具体的处理方法。
    • 根本原因:定义标准
    • 关键字:implements
    • 定义:全局常量(static final)和无实现的方法(Java8以后可以有default方法

一台汽车,既可以是电动车,也可以是汽油车,还可以是油电混合汽车,只要遵守不同的标准就行,但是一台车只能属于一个品牌、一个厂商。

class Car extends Benz implements GasolineCar, ElectroCar {}

4.组合与继承

4.1 继承复用

  • 继承是类或者接口与接口之间最常见的一种关系。继承是一种is-a的关系。

is-a:表示是一个的关系

Class_B
Class_A
哈士奇

4.2 组合复用

  • 组合体现的是整体与部分之间拥有的关系,即has-a的关系。

has-a:表示有一个的关系

Class_B
Class_A
汽车
发动机

4.3 组合和继承的区别和联系

  • 类的关系确定的时间点
    • 继承
      • 因为在写代码时就要指名具体继承哪个类,所以在编译期就确定了类的关系。
      • 并且从基类继承的实现是无法在运行期动态改变的,因此降低了应用的灵活性。
    • 组合
      • 在写代码时可以采用面向接口编程,所以类的组合关系一般在运行期确定。
  • 代码复用方式
    • 继承
      • 在继承结构中,父类的内部细节对于子类是可见的。通过继承的代码复用是一种白盒式代码复用。
      • 如果基类的实现发生改变,那么派生类的实现也将随之改变。这样就导致了子类行为的不可预知性。
    • 组合
      • 通过对现有的对象进行拼装(组合)产生新的、更复杂的功能。
      • 因为在对象之间,各自的内部细节是不可见的,所以我们也说这种方式的代码复用是黑盒式代码复用。
      • 在组合中一般都定义一个类型,所以在编译期根本不知道具体会调用哪个实现类的方法。

4.4 优缺点对比

组合关系 继承关系
优点:不破坏封装,整体类与局部类之间松耦合,彼此相对独立 缺点:破坏封装,子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性
优点:具有较好的可扩展性 缺点:支持扩展,但是往往以增加系统结构的复杂度为代价
优点:支持动态组合。在运行时,整体对象可以选择不同类型的局部对象 缺点:不支持动态继承。在运行时,子类无法选择不同的父类
优点:整体类可以对局部类进行包装,封装局部类的接口,提供新的接口 缺点:子类不能改变父类的接口
缺点:整体类不能自动获得和局部类同样的接口 优点:子类能自动继承父类的接口
缺点:当创建整体类的对象时,需要创建所有局部类的对象 优点:当创建子类的对象时,无须创建父类的对象

4.5 如何选择?

  • 建议在同样可行的情况下,优先使用组合而不是继承。因为组合更安全、更简单、更灵活、更高效。

5.构造函数

  • 构造函数:在创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符在创建对象的语句中一起使用。
/**
 * @description: 矩形
 */
public class Rectangle {
    /**
     * 构造函数
     */
    public Rectangle(int length, int width) {
        this.length = length;
        this.width = width;
    }
    
    public static void main(String[] args) {
        // 使用构造函数创建对象
        Rectangle rectangle = new Rectangle(10, 5);
    }
}
  • 特别的一个类可以有多个构造函数,可根据其参数个数的不同或参数类型的不同来区分,即构造函数的重载
  • 构造函数没有返回类型,不会被继承,而且可以有范围修饰符。
  • 构造器的函数名称必须和它的类名相同,它承担着初始化对象数据成员的任务。
  • 当一个没有编写构造函数时,会自动生成默认无参构造函数。默认构造函数会把成员变量的值初始化为默认值。
    • int->0Integer->null
  • 但是我们手动定义了一个有参数的构造函数,那么无参构造函数就不会自动添加了。
/**
 * @description: 矩形
 */
public class Rectangle {
    /**
     * 构造函数
     */
    public Rectangle(int length, int width) {
        this.length = length;
        this.width = width;
    }
    
    /**
     * 无参构造函数
     */
    public Rectangle() {
    }
}

6.变量

  • Java中共有三种变量,都存在JVM中。
    • 类变量 -> 方法区
    • 成员变量 -> 堆内存
    • 局部变量 -> 栈内存
/**
 * @description: 变量
 */
public class Variables {
    /**
     * 类变量
     */
    private static int a;
    /**
     * 成员变量
     */
    private int b;
    /**
     * 局部变量
     * @param c
     */
    public void test(int c) {
        int d;
    }
}

你可能感兴趣的:(Java核心技术-基础篇,java)