第21章
Java类和对象
理解面向对象编程的核心概念,掌握类的定义和对象的使用
学习目标
理解类和对象的概念及其关系
掌握类的定义语法和基本结构
学会创建和使用对象
理解构造方法的作用和重载
掌握实例变量和实例方法的使用
了解静态变量和静态方法的概念
理解封装的重要性和实现方法
学会使用getter和setter方法
面向对象编程概述
面向对象编程(Object-Oriented Programming,OOP)是一种编程范式,它将现实世界中的事物抽象为程序中的对象。Java是一门纯面向对象的编程语言,理解类和对象的概念是掌握Java编程的关键。
什么是面向对象编程?
面向对象编程是一种程序设计思想,它将数据和操作数据的方法封装在一起,形成对象。通过对象之间的交互来完成程序的功能。
类(Class)
类的定义:
public class Student {
// 属性(实例变量)
private String name;
private int age;
// 构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
}
// 方法
public void study() {
System.out.println(name + "正在学习");
}
}
对象的模板或蓝图
定义对象的属性和行为
使用class关键字定义
包含属性、构造方法和方法
对象(Object)
对象的创建和使用:
// 创建对象
Student student = new Student("张三", 20);
// 调用方法
student.study();
// 输出:张三正在学习
类的实例
具有类定义的属性和行为
使用new关键字创建
每个对象都有独立的状态
类的基本结构
Java类由以下几个主要部分组成:属性(实例变量)、构造方法、实例方法和静态成员。让我们通过一个完整的学生类示例来了解这些组成部分。
完整的学生类示例:
/**
* 学生类示例
* 演示类的基本结构和面向对象编程概念
*/
public class Student {
// 实例变量(属性)
private String name; // 学生姓名
private int age; // 学生年龄
private String studentId; // 学号
private String major; // 专业
// 默认构造方法
public Student() {
this.name = "未知";
this.age = 0;
this.studentId = "000000";
this.major = "未定";
}
// 带参数的构造方法
public Student(String name, int age, String studentId, String major) {
this.name = name;
this.age = age;
this.studentId = studentId;
this.major = major;
}
// 重载构造方法
public Student(String name, int age) {
this.name = name;
this.age = age;
this.studentId = "000000";
this.major = "未定";
}
// Getter方法
public String getName() {
return name;
}
public int getAge() {
return age;
}
// Setter方法
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
if (age > 0 && age < 150) {
this.age = age;
} else {
System.out.println("年龄输入不合法!");
}
}
// 实例方法
public void study() {
System.out.println(name + "正在学习");
}
public void study(String subject) {
System.out.println(name + "正在学习" + subject);
}
public void displayInfo() {
System.out.println("=== 学生信息 ===");
System.out.println("姓名: " + name);
System.out.println("年龄: " + age + "岁");
System.out.println("学号: " + studentId);
System.out.println("专业: " + major);
}
}
💻 查看完整代码 - 在线IDE体验
构造方法详解
构造方法是一种特殊的方法,用于创建对象时初始化对象的状态。构造方法的名称必须与类名相同,且没有返回类型。
默认构造方法
public Student() {
this.name = "未知";
this.age = 0;
this.studentId = "000000";
this.major = "未定";
}
无参数的构造方法
提供默认的初始化值
如果没有定义构造方法,Java会提供默认构造方法
带参数构造方法
public Student(String name, int age,
String studentId, String major) {
this.name = name;
this.age = age;
this.studentId = studentId;
this.major = major;
}
接受参数进行初始化
可以有多个不同参数的构造方法
构造方法重载
注意:一旦定义了带参数的构造方法,Java就不会自动提供默认构造方法。如果需要默认构造方法,必须显式定义。
静态变量和静态方法
静态成员属于类本身,而不是某个特定的对象。所有对象共享静态变量,静态方法可以通过类名直接调用。
汽车类示例 - 演示静态成员:
public class Car {
// 静态变量(类变量)
private static int totalCars = 0;
// 实例变量
private String brand;
private String model;
private double price;
// 构造方法
public Car(String brand, String model, double price) {
this.brand = brand;
this.model = model;
this.price = price;
totalCars++; // 每创建一个对象,总数加1
}
// 静态方法 - 获取汽车总数
public static int getTotalCars() {
return totalCars;
}
// 静态方法 - 比较两辆车的价格
public static void comparePrices(Car car1, Car car2) {
if (car1.price > car2.price) {
System.out.println(car1.brand + " " + car1.model + " 比 " +
car2.brand + " " + car2.model + " 贵");
} else if (car1.price < car2.price) {
System.out.println(car2.brand + " " + car2.model + " 比 " +
car1.brand + " " + car1.model + " 贵");
} else {
System.out.println("两辆车价格相同");
}
}
// 实例方法
public void displayInfo() {
System.out.println("品牌: " + brand);
System.out.println("型号: " + model);
System.out.println("价格: ¥" + price);
}
}
特性
实例成员
静态成员
归属
属于对象
属于类
内存分配
每个对象都有自己的副本
所有对象共享一份
访问方式
通过对象访问
通过类名或对象访问
生命周期
随对象创建和销毁
随类加载和卸载
封装的概念和实现
封装是面向对象编程的重要原则之一,它将数据和操作数据的方法结合在一起,并隐藏内部实现细节,只暴露必要的接口。
银行账户类 - 封装示例:
public class BankAccount {
// 私有属性,外部无法直接访问
private String accountNumber;
private String accountHolder;
private double balance;
private String password;
// 构造方法
public BankAccount(String accountNumber, String accountHolder,
double initialBalance, String password) {
this.accountNumber = accountNumber;
this.accountHolder = accountHolder;
this.password = password;
// 验证初始余额
if (initialBalance >= 0) {
this.balance = initialBalance;
} else {
this.balance = 0;
System.out.println("初始余额不能为负数,已设置为0");
}
}
// 存款方法
public boolean deposit(double amount, String inputPassword) {
// 验证密码
if (!verifyPassword(inputPassword)) {
System.out.println("密码错误,存款失败!");
return false;
}
// 验证金额
if (amount <= 0) {
System.out.println("存款金额必须大于0!");
return false;
}
balance += amount;
System.out.println("存款成功!当前余额: ¥" + balance);
return true;
}
// 取款方法
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.println("取款成功!当前余额: ¥" + balance);
return true;
}
// 私有方法 - 验证密码
private boolean verifyPassword(String inputPassword) {
return password != null && password.equals(inputPassword);
}
// 只提供必要的getter方法
public String getAccountNumber() {
return accountNumber;
}
public String getAccountHolder() {
return accountHolder;
}
// 注意:不提供getPassword()和setBalance()等方法
// 这样可以保护敏感数据的安全性
}
封装的好处:
数据安全:私有属性防止外部直接修改
数据验证:通过方法控制数据的修改
隐藏实现:内部实现细节对外不可见
易于维护:修改内部实现不影响外部代码
类和对象的最佳实践
编程最佳实践
✅ 好的做法
使用有意义的类名和方法名
public class BankAccount { // 清晰的类名
public boolean withdraw(double amount) { ... } // 清晰的方法名
}
合理使用访问修饰符
private String password; // 敏感数据设为私有
public void displayInfo() { // 公共接口设为公有
提供构造方法重载
public Student() { ... } // 默认构造
public Student(String name, int age) { ... } // 带参构造
实现数据验证
public void setAge(int age) {
if (age > 0 && age < 150) {
this.age = age;
}
}
❌ 应该避免的做法
直接暴露内部数据
public double balance; // 不安全,应该设为私有
缺少数据验证
public void setAge(int age) {
this.age = age; // 没有验证,可能设置无效值
}
过度复杂的类
// 一个类承担太多责任
class StudentTeacherManagerSystem { ... }
不合理的方法命名
public void doSomething() { ... } // 方法名不明确
public void a() { ... } // 方法名无意义
章节总结
类是对象的模板,定义了对象的属性和行为
对象是类的实例,通过new关键字创建
构造方法用于初始化对象,可以重载
实例变量属于对象,静态变量属于类
封装通过私有属性和公共方法保护数据安全
getter和setter方法提供受控的数据访问
良好的类设计遵循单一职责原则
合理使用访问修饰符控制成员的可见性
上一章:数组操作
章节测试
下一章:继承