Java面向对象程序设计教程
目录
- 前言:为什么是面向对象?
- 第一部分:Java OOP核心基石
- 1 万物皆对象:类与对象
- 2 对象的蓝图:类
- 3 从蓝图到实例:创建对象
- 4 对象的状态与行为:成员变量与方法
- 5 构造方法:对象的“出厂设置”
- 6
this关键字:指代当前对象
- 第二部分:OOP三大特性
- 1 封装:隐藏细节,保护数据
- 2 继承:代码复用与扩展
- 3 多态:同一接口,多种形态
- 第三部分:面向对象进阶
- 1 抽象类与接口
- 2
static关键字:静态成员 - 3 内部类
- 4 枚举
- 第四部分:实战演练——设计一个简单的学生管理系统
- 总结与学习资源
前言:为什么是面向对象?
在过程式编程(如C语言)中,我们关注的是“怎么做”——即一系列的步骤和函数,而面向对象编程则关注的是“谁来做”——即通过对象之间的交互来完成功能。

OOP的核心思想:
- 万物皆对象:将现实世界中的事物抽象成程序中的对象。
- 对象之间通过消息通信:一个对象通过调用另一个对象的方法来请求其服务。
- 程序由一系列相互作用的对象组成。
OOP的优势:
- 可维护性高:代码结构清晰,易于理解和修改。
- 可复用性强:通过继承和组合,可以复用已有的代码。
- 可扩展性好:可以轻松地添加新功能,而无需修改大量现有代码。
- 更贴近现实世界:建模方式自然,便于分析和设计。
第一部分:Java OOP核心基石
1 万物皆对象:类与对象
- 类:是对象的模板或蓝图,它定义了一类对象共有的属性(数据)和行为(方法)。“汽车”是一个类,它定义了所有汽车都有的属性(颜色、品牌、速度)和行为(启动、加速、刹车)。
- 对象:是类的具体实例,它是一个实实在在存在的个体,拥有类中定义的属性和行为。“我的那辆红色的特斯拉”汽车”类的一个对象。
关系:类是抽象的,对象是具体的,一个类可以创建多个对象。
2 对象的蓝图:类
在Java中,使用class关键字来定义一个类。

// Car.java - 定义一个名为 Car 的类
public class Car {
// 类的内容将在下面详细讲解
}
3 从蓝图到实例:创建对象
创建对象的过程称为实例化,使用 new 关键字来完成。
// 在另一个类(如 Main.java)中
public class Main {
public static void main(String[] args) {
// 使用 new 关键字创建 Car 类的一个实例
Car myCar = new Car();
Car anotherCar = new Car();
System.out.println(myCar); // 输出对象的内存地址
System.out.println(anotherCar); // 输出另一个对象的内存地址
}
}
4 对象的状态与行为:成员变量与方法
- 成员变量:定义对象的状态或属性,它们存储对象的数据,在类中直接定义的变量就是成员变量。
- 方法:定义对象的行为或操作,它们是对象可以执行的动作。
public class Car {
// 成员变量(属性)
String brand; // 品牌
String color; // 颜色
int speed; // 速度
// 方法(行为)
public void start() {
System.out.println("汽车启动了!");
this.speed = 0; // 启动时速度为0
}
public void accelerate(int increment) {
this.speed += increment;
System.out.println("汽车加速,当前速度: " + this.speed + " km/h");
}
public void stop() {
System.out.println("汽车停止了!");
this.speed = 0;
}
}
5 构造方法:对象的“出厂设置”
构造方法是一种特殊的方法,用于在创建对象时进行初始化,它的特点:
- 方法名与类名完全相同。
- 没有返回类型(连
void都没有)。 - 在创建对象时由
new关键字自动调用。
如果类中没有显式定义构造方法,Java编译器会提供一个默认的无参构造方法,一旦你定义了任何一个构造方法,默认的无参构造方法就不会再被自动提供了。
public class Car {
String brand;
String color;
// 无参构造方法
public Car() {
System.out.println("一个Car对象被创建了!");
}
// 带参构造方法,用于在创建对象时初始化品牌和颜色
public Car(String brand, String color) {
this.brand = brand; // 使用 this 关键字区分成员变量和参数
this.color = color;
System.out.println("一辆 " + color + " 的 " + brand + " 被创建了!");
}
}
// 使用
public class Main {
public static void main(String[] args) {
Car car1 = new Car(); // 调用无参构造方法
Car car2 = new Car("Tesla", "Red"); // 调用带参构造方法
}
}
6 this关键字:指代当前对象
this是一个引用变量,指向当前正在操作的对象,它主要用于:

- 区分成员变量和局部变量:当方法参数与成员变量同名时,使用
this.成员变量来访问成员变量。 - 调用本类的其他构造方法:
this()必须放在构造方法的第一行。
public class Person {
String name;
public Person(String name) {
this.name = name; // this.name 指的是成员变量 name
}
}
第二部分:OOP三大特性
1 封装
概念:将对象的属性和方法捆绑在一起,并对外部世界隐藏对象的内部细节,只暴露有限的接口(公共方法)与外部交互。
目的:
- 保护数据:防止外部代码随意修改对象内部状态。
- 隐藏实现细节:降低模块间的耦合度,修改内部实现不影响外部调用者。
实现方式:
- 将成员变量声明为
private(私有),使其只能在当前类内部访问。 - 提供公共的
public方法来访问和修改这些私有变量,这些方法通常称为 Getter 和 Setter。
public class Student {
// 1. 成员变量设为私有
private String name;
private int age;
// 2. 提供公共的 Getter 和 Setter 方法
public String getName() {
return this.name;
}
public void setName(String name) {
// 可以在这里添加业务逻辑,如数据校验
if (name != null && !name.isEmpty()) {
this.name = name;
}
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
if (age > 0) { // 添加校验逻辑
this.age = age;
}
}
}
2 继承
概念:允许一个类(子类/派生类)继承另一个类(父类/基类)的属性和方法,这实现了代码复用和层次化建模。
特点:
- Java只支持单继承,即一个类只能有一个直接父类,但可以通过接口实现多重继承的效果。
- 子类会自动获得父类的非私有成员(属性和方法)。
- 子类可以扩展父类的功能,也可以重写父类的方法。
关键字:
extends:用于声明继承关系。
// 父类
public class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " is eating.");
}
}
// 子类 Dog 继承自 Animal
public class Dog extends Animal {
// Dog 自动拥有 name 属性和 eat() 方法
public Dog(String name) {
// 使用 super() 调用父类的构造方法
super(name);
}
// Dog 特有的方法
public void bark() {
System.out.println("Woof! Woof!");
}
}
// 使用
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog("Buddy");
myDog.eat(); // 继承自 Animal 的方法
myDog.bark(); // Dog 自己的方法
}
}
3 多态
概念:指同一个接口,使用不同的实例而执行不同操作的能力,简单说就是:“父类引用指向子类对象”。
实现多态的三个必要条件:
- 继承:必须有类之间的继承关系。
- 重写:子类必须重写父类的方法。
- 父类引用指向子类对象:
Parent p = new Child();
优点:
- 提高代码的灵活性和可扩展性:在运行时才确定调用哪个对象的方法,便于程序扩展。
方法重写: 子类提供与父类相同方法签名(方法名、参数列表)的实现,以覆盖父类的实现,注意:
@Override注解:推荐使用,它可以编译器检查是否真的重写了父类方法,避免拼写错误。- 访问修饰符:子类重写方法的访问权限不能比父类更严格(父类是
public,子类不能是protected)。 - 返回类型:子类重写方法的返回类型必须是父类方法返回类型或其子类。
// 父类
class Animal {
public void makeSound() {
System.out.println("Animal makes a sound");
}
}
// 子类 1
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Woof! Woof!");
}
}
// 子类 2
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow!");
}
}
// 测试多态
public class Main {
public static void main(String[] args) {
// 父类引用指向子类对象
Animal myDog = new Dog();
Animal myCat = new Cat();
// 调用方法,在运行时根据实际对象类型决定调用哪个方法
myDog.makeSound(); // 输出: Woof! Woof!
myCat.makeSound(); // 输出: Meow!
}
}
第三部分:面向对象进阶
1 抽象类与接口
当父类的方法无法给出具体实现,或者只想定义一种“规范”让子类去遵守时,就需要抽象类或接口。
| 特性 | 抽象类 | 接口 |
|---|---|---|
| 定义 | 使用 abstract class 声明 |
使用 interface 声明 |
| 方法 | 可以包含抽象方法(无体)和具体方法(有体) | 从Java 8开始,可以包含抽象方法、默认方法 (default) 和静态方法 (static) |
| 成员变量 | 可以是任何类型 | 默认是 public static final (常量) |
| 继承 | 单继承 | 一个类可以实现多个接口 |
| 目的 | 提供部分实现,为相关类提供一个共同的基类 | 定义一种能力或契约,实现解耦 |
抽象类示例:
// 抽象类
abstract class Shape {
// 成员变量
String color;
// 构造方法
public Shape(String color) {
this.color = color;
}
// 抽象方法,没有方法体,必须由子类实现
public abstract double getArea();
// 具体方法
public void display() {
System.out.println("This is a " + color + " shape.");
}
}
// 子类
class Circle extends Shape {
double radius;
public Circle(String color, double radius) {
super(color);
this.radius = radius;
}
@Override
public double getArea() {
return Math.PI * radius * radius;
}
}
接口示例:
// 接口
interface Flyable {
// 抽象方法 (public abstract 是默认的,可以省略)
void fly();
// 默认方法 (Java 8+)
default void takeOff() {
System.out.println("Taking off...");
}
}
// 实现接口的类
class Bird implements Flyable {
@Override
public void fly() {
System.out.println("The bird is flying with its wings.");
}
}
class Airplane implements Flyable {
@Override
public void fly() {
System.out.println("The airplane is flying with engines.");
}
}
2 static关键字:静态成员
static 关键字可以用于修饰成员变量、成员方法、代码块和内部类。
- 静态成员变量:被所有对象共享,它不属于任何一个具体的对象,而是属于类本身,可以通过
类名.变量名或对象名.变量名来访问。 - 静态成员方法:也称为类方法,它没有隐式的
this参数,因此不能直接访问类的非静态成员(变量和方法),通常用于工具类或与类本身相关的操作。 - 静态代码块:在类加载时执行一次,通常用于初始化静态变量。
public class MyClass {
// 静态变量
static int staticCounter = 0;
// 实例变量
int instanceCounter = 0;
// 静态代码块
static {
System.out.println("静态代码块被执行,只执行一次。");
staticCounter = 100;
}
// 构造方法
public MyClass() {
staticCounter++;
instanceCounter++;
System.out.println("创建了一个对象。");
}
// 静态方法
public static void staticMethod() {
System.out.println("这是一个静态方法。");
// System.out.println(instanceCounter); // 编译错误:静态方法不能访问非静态成员
}
}
3 内部类
一个类定义在另一个类的内部,这个内部的类就叫做内部类。
- 成员内部类:作为外部类的成员,可以访问外部类的所有成员(包括私有)。
- 静态内部类:使用
static修饰,不能访问外部类的非静态成员。 - 局部内部类:定义在方法或作用域内。
- 匿名内部类:没有名字的内部类,常用于简化接口或抽象类的实现。
// 外部类
class Outer {
private int outerVar = 10;
// 成员内部类
class Inner {
public void display() {
System.out.println("外部类的变量: " + outerVar);
}
}
// 静态内部类
static class StaticInner {
public void show() {
// System.out.println(outerVar); // 编译错误:静态内部类不能访问非静态成员
}
}
}
4 枚举
enum 是一种特殊的类,用于表示一组固定的常量集合,它比用 public static final 定义的常量更安全、更易读。
// 定义一个枚举类型
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
public class EnumExample {
public static void main(String[] args) {
Day today = Day.FRIDAY;
switch (today) {
case MONDAY:
System.out.println("星期一,新的一周开始了。");
break;
case FRIDAY:
System.out.println("星期五,周末快到了!");
break;
default:
System.out.println("普通的一天。");
}
// 获取枚举的所有值
for (Day day : Day.values()) {
System.out.println(day);
}
}
}
第四部分:实战演练——设计一个简单的学生管理系统
让我们用学到的知识来设计一个简单的系统。
需求:能够添加学生,并显示所有学生的信息。
步骤:
-
定义
Student类:- 属性:
id(学号),name(姓名),age(年龄)。 - 将属性设为私有,提供Getter和Setter。
- 重写
toString()方法,方便打印学生信息。
- 属性:
-
定义
StudentManager类:- 属性:一个
List<Student>用来存储所有学生。 - 方法:
addStudent(Student s): 添加学生。showAllStudents(): 显示所有学生信息。
- 属性:一个
-
编写
Main类:- 创建
StudentManager实例。 - 循环菜单,让用户选择添加学生或查看学生。
- 创建
代码实现:
Student.java
import java.util.Objects;
public class Student {
private int id;
private String name;
private int age;
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
// Getters and Setters
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return id == student.id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
StudentManager.java
import java.util.ArrayList;
import java.util.List;
public class StudentManager {
private List<Student> students;
public StudentManager() {
this.students = new ArrayList<>();
}
public void addStudent(Student student) {
students.add(student);
System.out.println("学生 " + student.getName() + " 添加成功!");
}
public void showAllStudents() {
if (students.isEmpty()) {
System.out.println("当前没有学生信息。");
} else {
System.out.println("----- 所有学生信息 -----");
for (Student student : students) {
System.out.println(student);
}
System.out.println("-----------------------");
}
}
}
Main.java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
StudentManager manager = new StudentManager();
while (true) {
System.out.println("\n===== 学生管理系统 =====");
System.out.println("1. 添加学生");
System.out.println("2. 查看所有学生");
System.out.println("3. 退出");
System.out.print("请选择操作: ");
int choice = scanner.nextInt();
scanner.nextLine(); // 消耗换行符
switch (choice) {
case 1:
System.out.print("请输入学号: ");
int id = scanner.nextInt();
scanner.nextLine();
System.out.print("请输入姓名: ");
String name = scanner.nextLine();
System.out.print("请输入年龄: ");
int age = scanner.nextInt();
scanner.nextLine();
Student newStudent = new Student(id, name, age);
manager.addStudent(newStudent);
break;
case 2:
manager.showAllStudents();
break;
case 3:
System.out.println("感谢使用,再见!");
scanner.close();
System.exit(0);
default:
System.out.println("无效的输入,请重新选择!");
}
}
}
}
总结与学习资源
本教程从Java面向对象的基本概念(类、对象)出发,深入讲解了封装、继承、多态三大核心特性,并介绍了抽象类、接口、static关键字等进阶内容,最后通过一个完整的实战项目,将所有知识点串联起来,希望能帮助你建立对Java OOP的系统性认识。
学习建议:
- 动手编码:理论学得再多,不如亲手敲一遍代码,教程中的每个例子都请自己运行并修改。
- 多思考“为什么”:理解每个设计背后的思想,而不仅仅是语法。
- 阅读优秀代码:阅读Java标准库(如
java.util包)的源码,看看大师是如何设计的。 - 实践出真知:尝试设计自己的小项目,在实践中巩固知识。
推荐资源:
- 官方文档:Oracle Java Documentation (最权威、最准确)
- 经典书籍:
- 《Java核心技术 卷I》(Core Java Volume I):内容全面,适合入门和进阶。
- 《Effective Java》:Java编程的最佳实践,进阶必读。
- 在线教程:
- W3Schools Java Tutorial
- Runoob Java 教程
- 菜鸟教程 (廖雪峰老师的教程也很受欢迎)
