面向对象编程(OOP:Object Oriented Programming)。

1. 面向对象三大特征

面向对象三大特征分别为封装(Encapsulation),继承(Inheritance),多态(Polymorphism)。

1.1. 封装

Java中的封装思想和 C++ 相同。

1.2. 继承

继承关键字为 extends。 与C++ 类似。

1
class Subclass extends Superclass {}

注:

  1. 子类不能直接访问父类中 private 成员变量和方法。
  2. Java 只支持单继承,不允许多继承。即一个子类只能有一个父类,但一个父类可以派生出多个子类。

1.3. 多态

  1. 多态性是面向对象中最重要的概念,在 Java 中有两种体现。

    1. 方法的重载(overload)和重写(override);
    2. 对象的多态性:可以直接应用在抽象类和接口上。
  2. Java 引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。若编译时类型和运行时类型不一致,就出现多态。

  3. 在 Java 中,子类的对象可以代替父类的对象使用

    1. 一个变量只能有一种确定的数据类型;

    2. 一个引用变量可能指向(引用)多种不同类型的对象。

      1
      Person p = new Student();
    3. 子类可以看作是特殊的父类,所以父类类型的引用可以指向子类的对象:向上转型(upcasting)。

    4. 一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能访问子类中添加的属性和方法。因为属性是在编译时确定的,编译时 p 为 Person 类型,没有 Student 类型的成员变量。

  4. 虚拟方法调用(Virtual Method Invocation)

    1. 正常方法调用

      1
      2
      3
      4
      Person p = new Person();
      p.getInfo();
      Student s = new Student();
      s.getInfo();
    2. 虚拟方法调用(多态下)

      1
      2
      Person e = new Student();
      e.getInfo(); // 调用 Student 类的 getInfo() 方法
    3. 编译时类型和运行时类型

      编译时 e 为 Person 类型,而方法的调用是在运行时确定的,所以调用的是 Student 类的 getInfo() 方法。 —— 动态绑定

2. Class

  1. 成员:属性,方法,构造函数。

  2. Class的语法格式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 修饰符 class 类名 {
    // 属性声明;
    // 方法声明;
    // }
    // 说明:修饰符public,类的属性可以不初始化,类的属性有默认值。
    public class Person {
    public int age;
    public void showAge() {
    System.out.println(age);
    }
    }

3. 对象的创建和使用

  1. 使用 new 构造器 创建一个新的对象。
  2. 使用 对象名.对象成员 的方式访问对象成员(包括属性和方法)。与 C/C++ 相同。

4. 匿名对象

直接调用对象方法,而不定义对象的引用,这样的对象叫匿名对象。例如:

1
new Student().getAge();

5. 类的访问机制

  1. 在一个类中的访问机制:类中的方法可以直接访问类中的成员变量。(特例: static 方法访问非 static 成员变量,编译不通过。)
  2. 在不同类中的访问机制:先要创建访问类的对象,再用对象访问类中定义的成员。

6. 方法的重载(overload)

  1. 重载:在同一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同既可。
  2. 重载的特点:与返回值类型无关,只看参数列表,且参数列表必须不同(参数个数或参数类型不同)。调用时,根据方法的参数列表来区别。

7. 方法的重写(override)

在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。

注:

  1. 重写方法必须和被重写方法具有相同的方法名、参数列表和返回值类型(即只可重写函数体);
  2. 重写方法不能使用比被重写方法更严格的访问权限;
  3. 重写和被重写的方法必须同时为 static 的,或者同时为非 static 的;
  4. 子类方法抛出的异常不能大于父类被重写方法的异常。
  • 方法的重载和重写的区别:
  1. 重载:一个类可以有多个同名方法。
  2. 重写:子类可以重写父类的方法,覆盖父类的方法。

8. 可变个数的形参

1
2
3
4
// 采用数组形参来定义方法
public static void test(int a, String[] books);
// 采用可变个数形参来定义方法
public static void test(int a, String... books);

可变参数:方法参数部分指定参数类型的参数个数是可变多个。

声明方式:方法名(参数的类型名... 参数名)

可变参数方法的使用与方法参数部分使用数组是一致的。

方法的参数部分有可变形参,需要放在形参声明的最后。

9. 方法的参数传递

Java 中方法的参数传递方式只有一种,值传递。即将实际参数的副本传入方法内,而参数本身不受影响。

10. 四种访问权限修饰符

权限修饰符 同一个类 同一个包 不同包的子类 不同包的非子类
Private
Default
Protected
Public

​ 注:

​ 1. 对于 class 的权限修饰只可以用 public 和 default(缺省)。

​ 2. public 类可以在任何地方被访问;

​ 3. default 类只可以被同一个包内部的类访问。

11. 类的构造方法

Java中类的构造方法与 C++ 类似。

根据参数的不同,构造器可以分为以下两类:

  1. 隐式无参构造器(系统默认提供)。
  2. 显示定义的一个或多个构造器(无参或有参)。

注:

  1. Java 语言中,每个类都至少有一个构造器;
  2. 默认构造器的修饰符与所属类的修饰符一致;
  3. 一旦显式定义了构造器,系统就不再提供默认的构造器;
  4. 一个类可以创建多个重载的构造器;
  5. 父类的构造器不可被子类继承。

12. 关键字this

关键字this表示当前对象,或在一个构造器中调用类的其他构造方法。

表示当前对象 this.value,如果本类中没有此属性或方法,从父类中继续查找;

在一个构造器中调用本类的其他构造方法 this(x, y)

​ 注:

​ 1. 当形参与成员变量重名时,如果在方法内部需要使用成员变量,必须加 this 来表 明。

​ 2. 在任意方法内,在使用的成员变量前加 this 可以增加代码的可读性。

​ 3. 使用 this() 必须放在构造器的首行。

​ 4. 使用 this 调用本来中的其他构造器,要保证至少有一个构造器不是用 this 的。

13. 关键字 super

关键字super在 Java 类中使用 super 来调用父类中的指定操作。

  1. super 可用于访问父类中定义的属性;
  2. super 可以用于调用父类中定义的成员方法;
  3. super 可用于在子类构造方法中调用父类的构造器;
  4. 当子类与父类出现同名成员时,可以用 super 区分;
  5. super 的追溯不仅限于直接父类,包括各层级的全部父类(即超类);
  6. 若某方法在多层父类中有方法重写,则调用最近的一个;
  7. super 和 this 的用法相像,this代表本类对象的引用,super 代表父类内存空间的标识。

注:

  1. 子类中所有的构造器默认都会调用父类中空参数的构造器;
  2. 当父类中没有空参数的构造器时,子类的构造器必须通过 this() 或 super() 语句指定调用本类或者父类中相应的构造器,且必须放在构造器的第一行;
  3. 如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有无参的构造器,则编译出错。