前言

面向对象编程(Object-Oriented Programming,OOP)是Java语言的核心编程范式,也是现代软件开发的主流思想。Java作为一门纯面向对象的语言,其设计哲学就是”一切皆对象”。理解面向对象编程对于掌握Java至关重要。本文将系统介绍Java中面向对象编程的基础概念,包括类、对象、封装、构造方法等核心知识点,帮助您建立面向对象的编程思维。

面向对象编程概述

什么是面向对象

面向对象编程是一种程序设计范式,它将现实世界中的事物抽象为程序中的对象,通过对象之间的交互来完成程序功能。相比于面向过程编程,面向对象更贴近人类的思维方式。

面向对象的三大特性

graph TD
    A[面向对象编程] --> B[封装 Encapsulation]
    A --> C[继承 Inheritance]
    A --> D[多态 Polymorphism]
    
    B --> B1[隐藏内部实现细节]
    B --> B2[提供公共接口]
    B --> B3[保证数据安全]
    
    C --> C1[代码重用]
    C --> C2[建立类层次结构]
    C --> C3[实现is-a关系]
    
    D --> D1[同一接口多种实现]
    D --> D2[运行时动态绑定]
    D --> D3[提高代码灵活性]
    
    E[面向对象优势] --> E1[代码重用性高]
    E --> E2[维护性好]
    E --> E3[扩展性强]
    E --> E4[符合人类思维]

面向对象vs面向过程

特性 面向过程 面向对象
编程思路 自上而下,逐步分解 找对象,建立对象关系
程序结构 函数为主 类和对象为主
数据安全 数据和函数分离 数据封装在对象内
代码重用 函数调用 继承和多态
维护扩展 困难 相对容易

类与对象

类的概念

类是对象的模板或蓝图,它定义了对象的属性和行为。在Java中,类是创建对象的模板。

1
2
3
4
5
6
7
8
9
10
// 类的基本语法
[访问修饰符] class 类名 {
// 成员变量(属性)
数据类型 变量名;

// 成员方法(行为)
访问修饰符 返回类型 方法名(参数列表) {
// 方法体
}
}

对象的概念

对象是类的实例,是具体存在的个体。每个对象都有自己的属性值,但共享类定义的行为。

完整示例:学生类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
public class Student {
// 成员变量(属性)
private String name; // 姓名
private int age; // 年龄
private String studentId; // 学号
private double score; // 成绩

// 构造方法
public Student() {
this.name = "未知";
this.age = 0;
this.studentId = "000000";
this.score = 0.0;
}

public Student(String name, int age, String studentId) {
this.name = name;
this.age = age;
this.studentId = studentId;
this.score = 0.0;
}

// 成员方法(行为)
public void study(String subject) {
System.out.println(name + " 正在学习 " + subject);
}

public void takeExam(String subject, double score) {
this.score = score;
System.out.println(name + " 参加了 " + subject + " 考试,得分:" + score);
}

public void showInfo() {
System.out.println("学生信息:");
System.out.println("姓名:" + name);
System.out.println("年龄:" + age);
System.out.println("学号:" + studentId);
System.out.println("成绩:" + score);
}

// Getter和Setter方法
public String getName() {
return name;
}

public void setName(String name) {
if (name != null && !name.trim().isEmpty()) {
this.name = name;
}
}

public int getAge() {
return age;
}

public void setAge(int age) {
if (age > 0 && age < 150) {
this.age = age;
}
}

public String getStudentId() {
return studentId;
}

public void setStudentId(String studentId) {
this.studentId = studentId;
}

public double getScore() {
return score;
}

public void setScore(double score) {
if (score >= 0 && score <= 100) {
this.score = score;
}
}
}

对象的创建和使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class StudentTest {
public static void main(String[] args) {
// 创建对象
Student student1 = new Student();
Student student2 = new Student("张三", 20, "2019001");

// 使用对象
student1.setName("李四");
student1.setAge(19);
student1.setStudentId("2019002");

// 调用方法
student1.study("Java编程");
student1.takeExam("Java编程", 95.5);
student1.showInfo();

student2.study("数据结构");
student2.takeExam("数据结构", 88.0);
student2.showInfo();
}
}

类的成员详解

成员变量

成员变量也叫实例变量,是定义在类中、方法外的变量。每个对象都有自己的成员变量副本。

1
2
3
4
5
6
7
8
9
10
11
public class Car {
// 成员变量
private String brand; // 品牌
private String model; // 型号
private String color; // 颜色
private double price; // 价格
private boolean isRunning; // 是否在运行

// 类变量(静态变量)
private static int totalCars = 0; // 汽车总数
}

成员方法

成员方法定义了对象能够执行的行为。方法可以访问对象的成员变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public class Car {
// ... 成员变量

// 启动汽车
public void start() {
if (!isRunning) {
isRunning = true;
System.out.println(brand + " " + model + " 启动了");
} else {
System.out.println("汽车已经在运行中");
}
}

// 停止汽车
public void stop() {
if (isRunning) {
isRunning = false;
System.out.println(brand + " " + model + " 停止了");
} else {
System.out.println("汽车已经停止");
}
}

// 加速
public void accelerate(int speed) {
if (isRunning) {
System.out.println(brand + " " + model + " 加速到 " + speed + " km/h");
} else {
System.out.println("请先启动汽车");
}
}

// 获取汽车信息
public String getCarInfo() {
return String.format("品牌:%s,型号:%s,颜色:%s,价格:%.2f万",
brand, model, color, price);
}
}

构造方法

构造方法的特点

构造方法是一种特殊的方法,用于创建对象时初始化对象的状态。它具有以下特点:

  • 方法名必须与类名相同
  • 没有返回值类型(连void都不写)
  • 在创建对象时自动调用
  • 可以重载
graph TD
    A[构造方法] --> B[默认构造方法]
    A --> C[有参构造方法]
    A --> D[构造方法重载]
    
    B --> B1[无参数]
    B --> B2[系统自动提供]
    B --> B3[初始化默认值]
    
    C --> C1[接收参数]
    C --> C2[自定义初始化]
    C --> C3[灵活创建对象]
    
    D --> D1[多个构造方法]
    D --> D2[参数列表不同]
    D --> D3[提供多种创建方式]
    
    E[构造方法执行流程] --> E1[分配内存空间]
    E --> E2[调用构造方法]
    E --> E3[返回对象引用]

构造方法示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class Person {
private String name;
private int age;
private String gender;
private String address;

// 默认构造方法
public Person() {
this.name = "未知";
this.age = 0;
this.gender = "未知";
this.address = "未知";
System.out.println("调用默认构造方法");
}

// 带姓名的构造方法
public Person(String name) {
this(); // 调用默认构造方法
this.name = name;
System.out.println("调用带姓名的构造方法");
}

// 带姓名和年龄的构造方法
public Person(String name, int age) {
this(name); // 调用带姓名的构造方法
this.age = age;
System.out.println("调用带姓名和年龄的构造方法");
}

// 全参构造方法
public Person(String name, int age, String gender, String address) {
this.name = name;
this.age = age;
this.gender = gender;
this.address = address;
System.out.println("调用全参构造方法");
}

// 显示个人信息
public void showInfo() {
System.out.printf("姓名:%s,年龄:%d,性别:%s,地址:%s%n",
name, age, gender, address);
}
}

构造方法的使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class PersonTest {
public static void main(String[] args) {
// 使用不同的构造方法创建对象
Person person1 = new Person();
person1.showInfo();

Person person2 = new Person("张三");
person2.showInfo();

Person person3 = new Person("李四", 25);
person3.showInfo();

Person person4 = new Person("王五", 30, "男", "北京市");
person4.showInfo();
}
}

this关键字

this的作用

this关键字代表当前对象的引用,主要用于以下场景:

  1. 区分成员变量和局部变量
  2. 在构造方法中调用其他构造方法
  3. 返回当前对象的引用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class Rectangle {
private double width;
private double height;

public Rectangle(double width, double height) {
// 使用this区分成员变量和参数
this.width = width;
this.height = height;
}

public Rectangle(double side) {
// 使用this调用其他构造方法
this(side, side); // 创建正方形
}

public Rectangle setWidth(double width) {
this.width = width;
return this; // 返回当前对象引用,支持链式调用
}

public Rectangle setHeight(double height) {
this.height = height;
return this;
}

public double getArea() {
return this.width * this.height;
}

public void showInfo() {
System.out.printf("矩形:宽=%.2f,高=%.2f,面积=%.2f%n",
this.width, this.height, this.getArea());
}
}

this的链式调用示例

1
2
3
4
5
6
7
8
9
10
public class RectangleTest {
public static void main(String[] args) {
Rectangle rect = new Rectangle(0, 0);

// 链式调用
rect.setWidth(10.0)
.setHeight(5.0)
.showInfo();
}
}

封装性与访问修饰符

封装的概念

封装是面向对象编程的核心特性之一,它将数据和操作数据的方法结合在一起,隐藏对象的内部实现细节,只暴露必要的接口给外部使用。

访问修饰符

graph TD
    A[访问修饰符] --> B[private 私有]
    A --> C[default 包私有]
    A --> D[protected 受保护]
    A --> E[public 公开]
    
    B --> B1[只能在本类中访问]
    B --> B2[最严格的访问控制]
    
    C --> C1[同包中可以访问]
    C --> C2[不写修饰符的默认级别]
    
    D --> D1[同包或子类中可以访问]
    D --> D2[为继承设计]
    
    E --> E1[任何地方都可以访问]
    E --> E2[最宽松的访问控制]
    
    F[封装原则] --> F1[数据私有化]
    F --> F2[方法公开化]
    F --> F3[提供合理的访问接口]

封装的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
public class BankAccount {
// 私有成员变量
private String accountNumber;
private String accountHolder;
private double balance;
private String password;

// 构造方法
public BankAccount(String accountNumber, String accountHolder, String password) {
this.accountNumber = accountNumber;
this.accountHolder = accountHolder;
this.password = password;
this.balance = 0.0;
}

// 公共方法:存款
public boolean deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.printf("存款成功,存入%.2f元,当前余额:%.2f元%n", amount, balance);
return true;
} else {
System.out.println("存款金额必须大于0");
return false;
}
}

// 公共方法:取款
public boolean withdraw(double amount, String inputPassword) {
if (!verifyPassword(inputPassword)) {
System.out.println("密码错误");
return false;
}

if (amount <= 0) {
System.out.println("取款金额必须大于0");
return false;
}

if (amount > balance) {
System.out.println("余额不足");
return false;
}

balance -= amount;
System.out.printf("取款成功,取出%.2f元,当前余额:%.2f元%n", amount, balance);
return true;
}

// 私有方法:验证密码
private boolean verifyPassword(String inputPassword) {
return this.password.equals(inputPassword);
}

// 公共方法:查询余额
public double getBalance(String inputPassword) {
if (verifyPassword(inputPassword)) {
return balance;
} else {
System.out.println("密码错误,无法查询余额");
return -1;
}
}

// 公共方法:修改密码
public boolean changePassword(String oldPassword, String newPassword) {
if (verifyPassword(oldPassword)) {
this.password = newPassword;
System.out.println("密码修改成功");
return true;
} else {
System.out.println("原密码错误");
return false;
}
}

// 只读属性的getter方法
public String getAccountNumber() {
return accountNumber;
}

public String getAccountHolder() {
return accountHolder;
}
}

static关键字与静态成员

static的概念

static关键字用于创建独立于对象的成员,这些成员属于类而不是某个特定的对象。

静态变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Counter {
private int instanceCount; // 实例变量
private static int totalCount = 0; // 静态变量

public Counter() {
instanceCount = 1;
totalCount++;
}

public void increment() {
instanceCount++;
totalCount++;
}

public int getInstanceCount() {
return instanceCount;
}

public static int getTotalCount() {
return totalCount;
}

public void showCounts() {
System.out.printf("实例计数:%d,总计数:%d%n", instanceCount, totalCount);
}
}

静态方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class MathUtils {
// 静态常量
public static final double PI = 3.14159265359;

// 静态方法:计算圆的面积
public static double calculateCircleArea(double radius) {
return PI * radius * radius;
}

// 静态方法:计算最大值
public static int max(int a, int b) {
return a > b ? a : b;
}

// 静态方法:判断是否为素数
public static boolean isPrime(int number) {
if (number < 2) {
return false;
}

for (int i = 2; i <= Math.sqrt(number); i++) {
if (number % i == 0) {
return false;
}
}
return true;
}
}

静态代码块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class DatabaseConfig {
private static String databaseUrl;
private static String username;
private static String password;

// 静态代码块:类加载时执行
static {
System.out.println("正在初始化数据库配置...");
databaseUrl = "jdbc:mysql://localhost:3306/mydb";
username = "root";
password = "password";
System.out.println("数据库配置初始化完成");
}

public static void showConfig() {
System.out.println("数据库URL:" + databaseUrl);
System.out.println("用户名:" + username);
}
}

面向对象设计实例

图书管理系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
// 图书类
public class Book {
private String isbn;
private String title;
private String author;
private double price;
private boolean isAvailable;

public Book(String isbn, String title, String author, double price) {
this.isbn = isbn;
this.title = title;
this.author = author;
this.price = price;
this.isAvailable = true;
}

public void borrow() {
if (isAvailable) {
isAvailable = false;
System.out.println("《" + title + "》借阅成功");
} else {
System.out.println("《" + title + "》已被借出");
}
}

public void returnBook() {
if (!isAvailable) {
isAvailable = true;
System.out.println("《" + title + "》归还成功");
} else {
System.out.println("《" + title + "》未被借出");
}
}

public void showInfo() {
System.out.printf("ISBN:%s,书名:%s,作者:%s,价格:%.2f,状态:%s%n",
isbn, title, author, price,
isAvailable ? "可借" : "已借出");
}

// Getter方法
public String getIsbn() { return isbn; }
public String getTitle() { return title; }
public String getAuthor() { return author; }
public double getPrice() { return price; }
public boolean isAvailable() { return isAvailable; }
}

// 图书馆类
public class Library {
private String name;
private Book[] books;
private int bookCount;
private static final int MAX_BOOKS = 1000;

public Library(String name) {
this.name = name;
this.books = new Book[MAX_BOOKS];
this.bookCount = 0;
}

public void addBook(Book book) {
if (bookCount < MAX_BOOKS) {
books[bookCount++] = book;
System.out.println("图书《" + book.getTitle() + "》添加成功");
} else {
System.out.println("图书馆已满,无法添加更多图书");
}
}

public Book findBookByIsbn(String isbn) {
for (int i = 0; i < bookCount; i++) {
if (books[i].getIsbn().equals(isbn)) {
return books[i];
}
}
return null;
}

public void showAllBooks() {
System.out.println("=== " + name + " 图书列表 ===");
for (int i = 0; i < bookCount; i++) {
books[i].showInfo();
}
}
}

总结

面向对象编程是Java的核心,本文全面介绍了面向对象编程的基础知识:

  1. 面向对象概述:理解OOP的核心思想和三大特性
  2. 类与对象:掌握类的定义和对象的创建使用
  3. 成员变量和方法:学会定义类的属性和行为
  4. 构造方法:掌握对象的初始化机制
  5. this关键字:理解当前对象引用的使用
  6. 封装性:学会使用访问修饰符控制访问权限
  7. static关键字:理解静态成员的特点和使用场景

面向对象编程提供了一种更自然、更符合人类思维的编程方式。通过封装,我们可以隐藏实现细节,提高代码的安全性;通过合理的类设计,我们可以创建出可重用、易维护的代码。掌握这些基础概念是学习Java高级特性(继承、多态等)的前提。

参考资料

  1. Oracle Java Documentation - Classes and Objects
  2. Effective Java by Joshua Bloch
  3. Head First Object-Oriented Analysis and Design
  4. Java核心技术卷I - 面向对象程序设计