面向对象程序设计的知识梳理
一.面向对象的基本概念
1.类与对象
类:是对具有相同属性和行为的一组对象的抽象描述,定义了对象的属性(成员变量)和行为(成员方法)。类的使用:使用 class 关键字,格式为 [修饰符] class 类名 [extends 父类名] [implements 接口名列表] 。
对象:是类的实例,通过 new 关键字创建,每个对象都有自己独立的属性值,可调用类中定义的方法。
2.封装
是将对象的属性和实现细节隐藏起来,仅对外提供公共的访问方法。通过将成员变量声明为 private, 并提供public 的 getter 和 setter 方法来实现。
3.继承
- 是面向对象编程的重要特性,通过 extends 关键字实现。子类可以继承父类的属性和方法,还可以添加自己特有的属性和方法,或重写父类的方法。
继承示例
class Parent {
public void parentMethod() {
System.out.println("Parent method.");
}
}
class Child extends Parent {
@Override
public void parentMethod() {
System.out.println("Child overridden method.");
}
}
4.多态
- 指同一个方法在不同的对象上有不同的表现形式。Java中的多态有两种实现方式:方法重载和方法重写。
- 方法重载:在同一个类中,允许存在多个方法名相同但参数列表不同的方法,根据参数的不同来调用不同的方法。
- 方法重写:子类中重新定义父类中已有的方法,要求方法签名(方法名、参数列表、返回值类型)相同,子类方法的访问权限不能比父类更严格。
多态示例
Parent parent1 = new Parent();
Parent parent2 = new Child();
parent1.parentMethod(); // 输出 "Parent method."
parent2.parentMethod(); // 输出 "Child overridden method."
类的定义与使用
public class MyClass {
// 成员变量
private int myVariable;
// 构造方法
public MyClass(int value) {
myVariable = value;
}
// 成员方法
public void myMethod() {
System.out.println("My method is called.");
}
}
二.类的构造方法
1.定义与特点
定义:构造方法是类中的特殊方法,用于创建对象时初始化对象的属性。
特点:方法名与类名相同,没有返回值类型(包括 void 也不能有),在创建对象时由 new 关键字自动调用。
2.构造方法的类型
无参构造方法:没有参数的构造方法,若类中未显式定义构造方法,Java会自动提供一个默认的无参构造方法,用于对对象的属性进行默认初始化。
有参构造方法:带有参数的构造方法,参数用于接收创建对象时传入的数据,以便对对象的属性进行特定的初始化。
构造方法的重载
类中可以定义多个构造方法,只要它们的参数列表不同(参数个数、类型或顺序不同),这就是构造方法的重载。通过重载,可以根据不同的需求,以多种方式创建对象。
3.构造方法的作用
初始化对象属性:将传入构造方法的参数值赋给对象的属性,确保对象在创建后就具有合理的初始值。
4.构造方法的访问修饰符
常见的有 public 、 private 、 protected 和默认(包访问权限)。 public 构造方法可被其他类访问; private 构造方法只能在类内部使用,常用于单例模式; protected 构造方法用于子类继承父类构造方法,在同一包或子类中可访问;默认修饰符的构造方法在同一包内可访问。
三.控制结构
1.顺序结构
是程序中最基本的控制结构,按照语句出现的先后顺序依次执行。
2.选择结构
if - else 语句:根据条件判断结果来决定执行不同的代码块。 if 后面的条件为 true 时执行 if 语句块,否则执行 else 语句块。还可以通过 else if 进行多条件判断。
switch 语句:根据表达式的值与多个 case 常量表达式的值进行匹配,匹配成功则执行对应 case 后的代码块,直到遇到 break 语句或 switch 语句结束。 default 分支用于处理所有不匹配 case 的情况。
3.循环结构
while 循环:先判断条件,条件为 true 时执行循环体,执行完循环体后再次判断条件,直到条件为 false 时结束循环。
do - while 循环:先执行一次循环体,然后判断条件,条件为 true 时继续执行循环体,直到条件为 false 。与 while 循环的区别是 do - while 循环至少会执行一次循环体。
for 循环:常用于已知循环次数的情况。包括初始化表达式、循环条件和迭代表达式,先执行初始化表达式,然后判断循环条件,条件为 true 时执行循环体,执行完循环体后执行迭代表达式,再判断循环条件,如此循环,直到条件为 false 。
4.跳转语句
break 语句:用于跳出当前循环或 switch 语句。在多层循环中,可通过标签与 break 配合,跳出指定的外层循环。
continue 语句:用于结束本次循环,直接进入下一次循环的条件判断。同样可与标签配合,在多层循环中指定作用的循环层。
四.抽象类与接口
1.定义与概念
抽象类:包含抽象方法(只有方法签名,没有方法体)的类,必须被 abstract 关键字修饰。它不能被实例化,只能被继承。
接口:是一种抽象类型,由方法签名和常量声明组成,所有方法默认是 public 和 abstract 的,所有常量默认是 public 、 static 和 final 的。接口不能被实例化,类通过实现接口来表明它提供了接口中定义的行为。
2.语法区别
抽象类:可以包含抽象方法和非抽象方法、成员变量、构造方法等。
接口:只能包含抽象方法(Java 8开始允许有默认方法和静态方法)、常量,不能有成员变量和构造方法。
3.关系与实现
抽象类:使用 extends 关键字来继承,一个类只能继承一个抽象类。
接口:使用 implements 关键字来实现,一个类可以实现多个接口。
4.设计目的
抽象类:用于抽取相关类的共性,包括属性和行为,作为它们的公共父类,实现代码复用。
接口:用于定义一组规范或契约,要求实现类必须遵循这些规范,强调行为的一致性,常用于解不同模块之间的关系。
5.应用场景
抽象类:当存在一系列相关的类,它们有一些共同的属性和行为,并且这些行为在不同类中有不同的实现时,可使用抽象类。如不同类型的图形类可继承抽象的图形类。
接口:当需要定义一组标准的行为,而不关心具体实现,或者希望实现多态性和可扩展性时,可使用接口。如各种支付方式可实现支付接口。
五.内部类与外部类
1.定义与概念
外部类:是指在Java源文件中直接定义的类,它是独立的、最外层的类,其定义不依赖于其他类。
内部类:是定义在另一个类内部的类,它作为外部类的成员存在,可以访问外部类的成员,包括私有成员。
2.内部类的类型
成员内部类:定义在外部类的成员位置,与外部类的成员变量和方法同级。可以访问外部类的所有成员,有自己独立的生命周期,可通过外部类对象来创建成员内部类对象。
静态内部类:使用 static 关键字修饰的内部类。它不能直接访问外部类的非静态成员,只能访问外部类的静态成员。创建静态内部类对象不需要依赖外部类对象。
局部内部类:定义在方法或代码块内部的类。只能在定义它的方法或代码块内使用,其作用域仅限于该方法或代码块。可以访问外部类的成员以及方法或代码块内的局部变量,但局部变量必须是 final 或事实上的 final 。
匿名内部类:没有类名的内部类,通常用于创建一次性使用的类对象。它必须继承一个父类或实现一个接口,在定义时同时创建对象并实现抽象方法或重写父类方法。
3.内部类与外部类的关系
成员访问:内部类可以直接访问外部类的成员,包括私有成员。外部类要访问内部类成员,需要通过内部类对象来访问。
生命周期:成员内部类的生命周期与外部类对象紧密相关,当外部类对象被销毁时,成员内部类对象也会被销毁。静态内部类的生命周期不依赖于外部类对象,它随着类的加载而存在,随着类的卸载而消失。
编译:内部类在编译后会生成独立的字节码文件,其文件名格式为 OuterClass$InnerClass.class ,其中 OuterClass 是外部类名, InnerClass 是内部类名
六.静态成员
1.定义与特点
定义:静态成员是在类中使用 static 关键字修饰的成员,包括静态变量和静态方法。
特点:静态成员属于类本身,而不属于类的某个具体对象。无论创建多少个类的对象,静态成员都只有一份,被所有对象共享。
2.静态变量
声明与初始化:在类中使用 static 关键字声明,可在声明时直接初始化,也可在静态代码块中初始化。例如: static int num = 10; 或先声明 static int num; ,然后在静态代码块中 static { num = 10; } 。
访问方式:可通过类名直接访问,如 ClassName.staticVariableName ,也可通过对象访问,但不推荐,因为静态变量不属于特定对象。
3.静态方法
声明:使用 static 关键字修饰方法,如 public static void staticMethod() { } 。
特点:静态方法只能访问静态成员,不能直接访问非静态成员,因为非静态成员依赖于具体对象。
调用方式:通过类名直接调用,如 ClassName.staticMethodName() 。
七.异常处理
1.异常概念
异常是指程序在运行过程中出现的错误或不正常情况,它会中断程序的正常执行流程。
2.异常分类
受检异常:是编译时异常,在编译阶段就必须处理,否则代码无法通过编译,如 IOException 等。
非受检异常:包括运行时异常和错误。运行时异常如 NullPointerException 等,在运行时才可能出现,编译阶段不强制处理。错误一般指 Error 及其子类,如 OutOfMemoryError ,通常是由系统级问题导致,一般不建议在程序中进行处理
3.异常处理机制
try - catch 语句: try 块中放置可能会抛出异常的代码, catch 块用于捕获并处理特定类型的异常。可以有多个 catch 块来处理不同类型的异常。例如:
try {
// 可能出现异常的代码
int result = 10 / 0;
} catch (ArithmeticException e) {
// 处理异常的代码
System.out.println("出现算术异常:" + e.getMessage());
}
finally 块:无论 try 块中的代码是否抛出异常, finally 块中的代码都会执行,常用于资源释放等操作。如:
try {
// 打开文件等操作
} catch (IOException e) {
// 处理异常
} finally {
// 关闭文件等资源释放操作
}
throw 关键字:用于在方法内部手动抛出异常。例如:
public void checkAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数");
}
}
throws 关键字:在方法签名中使用,用于声明该方法可能会抛出的异常,将异常处理交给调用者。如:
java
public void readFile() throws IOException {
// 读取文件的代码,可能抛出IOException
}
4.自定义异常
可以通过继承 Exception 类或其子类来定义自定义异常,以便在特定业务场景下抛出和处理异常,使代码更具可读性和可维护性。例如:
java
class MyException extends Exception {
public MyException(String message) {
super(message);
}
}