面向对象编程(OOP:Object Oriented Programming)。
1. 面向对象三大特征
面向对象三大特征分别为封装(Encapsulation),继承(Inheritance),多态(Polymorphism)。
1.1. 封装
Java中的封装思想和 C++ 相同。
1.2. 继承
继承关键字为 extends
。 与C++ 类似。
1 | class Subclass extends Superclass {} |
注:
- 子类不能直接访问父类中 private 成员变量和方法。
- Java 只支持单继承,不允许多继承。即一个子类只能有一个父类,但一个父类可以派生出多个子类。
1.3. 多态
多态性是面向对象中最重要的概念,在 Java 中有两种体现。
- 方法的重载(overload)和重写(override);
- 对象的多态性:可以直接应用在抽象类和接口上。
Java 引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。若编译时类型和运行时类型不一致,就出现多态。
在 Java 中,子类的对象可以代替父类的对象使用
一个变量只能有一种确定的数据类型;
一个引用变量可能指向(引用)多种不同类型的对象。
1
Person p = new Student();
子类可以看作是特殊的父类,所以父类类型的引用可以指向子类的对象:向上转型(upcasting)。
一个引用类型变量如果声明为父类的类型,但实际引用的是子类对象,那么该变量就不能访问子类中添加的属性和方法。因为属性是在编译时确定的,编译时 p 为 Person 类型,没有 Student 类型的成员变量。
虚拟方法调用(Virtual Method Invocation)
正常方法调用
1
2
3
4Person p = new Person();
p.getInfo();
Student s = new Student();
s.getInfo();虚拟方法调用(多态下)
1
2Person e = new Student();
e.getInfo(); // 调用 Student 类的 getInfo() 方法编译时类型和运行时类型
编译时 e 为 Person 类型,而方法的调用是在运行时确定的,所以调用的是 Student 类的 getInfo() 方法。 —— 动态绑定
2. Class
成员:属性,方法,构造函数。
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. 对象的创建和使用
- 使用
new 构造器
创建一个新的对象。 - 使用
对象名.对象成员
的方式访问对象成员(包括属性和方法)。与 C/C++ 相同。
4. 匿名对象
直接调用对象方法,而不定义对象的引用,这样的对象叫匿名对象。例如:
1 | new Student().getAge(); |
5. 类的访问机制
- 在一个类中的访问机制:类中的方法可以直接访问类中的成员变量。(特例: static 方法访问非 static 成员变量,编译不通过。)
- 在不同类中的访问机制:先要创建访问类的对象,再用对象访问类中定义的成员。
6. 方法的重载(overload)
- 重载:在同一个类中,允许存在一个以上的同名方法,只要他们的参数个数或者参数类型不同既可。
- 重载的特点:与返回值类型无关,只看参数列表,且参数列表必须不同(参数个数或参数类型不同)。调用时,根据方法的参数列表来区别。
7. 方法的重写(override)
在子类中可以根据需要对从父类中继承来的方法进行改造,也称为方法的重置、覆盖。在程序执行时,子类的方法将覆盖父类的方法。
注:
- 重写方法必须和被重写方法具有相同的方法名、参数列表和返回值类型(即只可重写函数体);
- 重写方法不能使用比被重写方法更严格的访问权限;
- 重写和被重写的方法必须同时为 static 的,或者同时为非 static 的;
- 子类方法抛出的异常不能大于父类被重写方法的异常。
- 方法的重载和重写的区别:
- 重载:一个类可以有多个同名方法。
- 重写:子类可以重写父类的方法,覆盖父类的方法。
8. 可变个数的形参
1 | // 采用数组形参来定义方法 |
可变参数:方法参数部分指定参数类型的参数个数是可变多个。
声明方式:方法名(参数的类型名... 参数名)
可变参数方法的使用与方法参数部分使用数组是一致的。
方法的参数部分有可变形参,需要放在形参声明的最后。
9. 方法的参数传递
Java 中方法的参数传递方式只有一种,值传递。即将实际参数的副本传入方法内,而参数本身不受影响。
10. 四种访问权限修饰符
权限修饰符 | 同一个类 | 同一个包 | 不同包的子类 | 不同包的非子类 |
---|---|---|---|---|
Private | √ | |||
Default | √ | √ | ||
Protected | √ | √ | √ | |
Public | √ | √ | √ | √ |
注:
1. 对于 class 的权限修饰只可以用 public 和 default(缺省)。
2. public 类可以在任何地方被访问;
3. default 类只可以被同一个包内部的类访问。
11. 类的构造方法
Java中类的构造方法与 C++ 类似。
根据参数的不同,构造器可以分为以下两类:
- 隐式无参构造器(系统默认提供)。
- 显示定义的一个或多个构造器(无参或有参)。
注:
- Java 语言中,每个类都至少有一个构造器;
- 默认构造器的修饰符与所属类的修饰符一致;
- 一旦显式定义了构造器,系统就不再提供默认的构造器;
- 一个类可以创建多个重载的构造器;
- 父类的构造器不可被子类继承。
12. 关键字this
关键字this
表示当前对象,或在一个构造器中调用类的其他构造方法。
表示当前对象 this.value
,如果本类中没有此属性或方法,从父类中继续查找;
在一个构造器中调用本类的其他构造方法 this(x, y)
。
注:
1. 当形参与成员变量重名时,如果在方法内部需要使用成员变量,必须加 this 来表 明。
2. 在任意方法内,在使用的成员变量前加 this 可以增加代码的可读性。
3. 使用 this() 必须放在构造器的首行。
4. 使用 this 调用本来中的其他构造器,要保证至少有一个构造器不是用 this 的。
13. 关键字 super
关键字super
在 Java 类中使用 super 来调用父类中的指定操作。
- super 可用于访问父类中定义的属性;
- super 可以用于调用父类中定义的成员方法;
- super 可用于在子类构造方法中调用父类的构造器;
- 当子类与父类出现同名成员时,可以用 super 区分;
- super 的追溯不仅限于直接父类,包括各层级的全部父类(即超类);
- 若某方法在多层父类中有方法重写,则调用最近的一个;
- super 和 this 的用法相像,this代表本类对象的引用,super 代表父类内存空间的标识。
注:
- 子类中所有的构造器默认都会调用父类中空参数的构造器;
- 当父类中没有空参数的构造器时,子类的构造器必须通过 this() 或 super() 语句指定调用本类或者父类中相应的构造器,且必须放在构造器的第一行;
- 如果子类构造器中既未显式调用父类或本类的构造器,且父类中又没有无参的构造器,则编译出错。