面向对象编程
本章内容
本章介绍 Java 面向对象编程的核心概念:类与对象、继承、多态、封装,以及访问修饰符和 final 关键字。
一、类与对象
1.1 类的定义
类是对象的模板,定义了对象的属性和行为:
public class Student {
// 属性(成员变量)
private String name;
private int age;
private double score;
// 构造方法
public Student() {
// 无参构造方法
}
public Student(String name, int age, double score) {
this.name = name;
this.age = age;
this.score = score;
}
// 方法(成员方法)
public void study() {
System.out.println(name + "正在学习");
}
public void showInfo() {
System.out.println("姓名:" + name + ",年龄:" + age + ",成绩:" + score);
}
// getter 和 setter 方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
if (age > 0 && age < 150) {
this.age = age;
}
}
public double getScore() {
return score;
}
public void setScore(double score) {
if (score >= 0 && score <= 100) {
this.score = score;
}
}
}
1.2 对象的创建和使用
public class TestStudent {
public static void main(String[] args) {
// 创建对象
Student student1 = new Student();
Student student2 = new Student("张三", 20, 85.5);
// 使用对象
student1.setName("李四");
student1.setAge(19);
student1.setScore(92.0);
student1.showInfo();
student1.study();
student2.showInfo();
student2.study();
}
}
1.3 this 关键字
this 关键字代表当前对象的引用:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name; // this.name 指当前对象的 name 属性
this.age = age; // this.age 指当前对象的 age 属性
}
public void setName(String name) {
this.name = name; // 区分参数 name 和属性 name
}
public Person getOlder(Person other) {
return this.age > other.age ? this : other;
}
public void introduce() {
System.out.println("我是 " + this.name); // this 可以省略
this.showAge(); // 调用当前对象的方法
}
private void showAge() {
System.out.println("我今年 " + age + " 岁");
}
}
二、封装(Encapsulation)
2.1 封装的概念
封装是将数据和操作数据的方法绑定在一起,并隐藏内部实现细节:
public class BankAccount {
private double balance; // 私有属性,外部无法直接访问
private String accountNumber;
public BankAccount(String accountNumber, double initialBalance) {
this.accountNumber = accountNumber;
this.balance = initialBalance;
}
// 提供公共方法来操作私有数据
public void deposit(double amount) {
if (amount > 0) {
balance += amount;
System.out.println("存款成功,余额:" + balance);
} else {
System.out.println("存款金额必须大于0");
}
}
public void withdraw(double amount) {
if (amount > 0 && amount <= balance) {
balance -= amount;
System.out.println("取款成功,余额:" + balance);
} else {
System.out.println("取款失败:金额无效或余额不足");
}
}
public double getBalance() {
return balance; // 只读访问
}
public String getAccountNumber() {
return accountNumber;
}
}
2.2 访问修饰符
| 修饰符 | 同一类 | 同一包 | 不同包子类 | 不同包非子类 |
|---|---|---|---|---|
private | ✓ | ✗ | ✗ | ✗ |
| 默认(包访问) | ✓ | ✓ | ✗ | ✗ |
protected | ✓ | ✓ | ✓ | ✗ |
public | ✓ | ✓ | ✓ | ✓ |
public class AccessExample {
private int privateField = 1; // 只能在本类中访问
int packageField = 2; // 包访问权限
protected int protectedField = 3; // 受保护访问权限
public int publicField = 4; // 公共访问权限
private void privateMethod() {
System.out.println("私有方法");
}
void packageMethod() {
System.out.println("包访问方法");
}
protected void protectedMethod() {
System.out.println("受保护方法");
}
public void publicMethod() {
System.out.println("公共方法");
privateMethod(); // 在同一类中可以访问私有方法
}
}
三、继承(Inheritance)
3.1 继承的基本概念
继承允许一个类获得另一个类的属性和方法:
// 父类(基类、超类)
public class Animal {
protected String name;
protected int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public void eat() {
System.out.println(name + "正在吃东西");
}
public void sleep() {
System.out.println(name + "正在睡觉");
}
public void showInfo() {
System.out.println("名字:" + name + ",年龄:" + age);
}
}
// 子类(派生类)
public class Dog extends Animal {
private String breed; // 子类特有属性
public Dog(String name, int age, String breed) {
super(name, age); // 调用父类构造方法
this.breed = breed;
}
// 子类特有方法
public void bark() {
System.out.println(name + "正在汪汪叫");
}
// 重写父类方法
@Override
public void showInfo() {
super.showInfo(); // 调用父类方法
System.out.println("品种:" + breed);
}
}
// 另一个子类
public class Cat extends Animal {
public Cat(String name, int age) {
super(name, age);
}
public void meow() {
System.out.println(name + "正在喵喵叫");
}
@Override
public void eat() {
System.out.println(name + "正在优雅地吃猫粮");
}
}
3.2 super 关键字
super 关键字用于访问父类的成员:
public class Vehicle {
protected String brand;
protected double speed;
public Vehicle(String brand) {
this.brand = brand;
this.speed = 0;
}
public void start() {
System.out.println(brand + "启动了");
}
public void accelerate(double increment) {
speed += increment;
System.out.println("当前速度:" + speed + " km/h");
}
}
public class Car extends Vehicle {
private int doors;
public Car(String brand, int doors) {
super(brand); // 调用父类构造方法
this.doors = doors;
}
@Override
public void start() {
super.start(); // 调用父类的 start 方法
System.out.println("汽车准备就绪");
}
@Override
public void accelerate(double increment) {
if (speed + increment <= 200) { // 汽车限速
super.accelerate(increment); // 调用父类方法
} else {
System.out.println("超速警告!");
}
}
}
3.3 方法重写(Override)
子类可以重写父类的方法来提供特定的实现:
public class Shape {
protected double area;
public void calculateArea() {
System.out.println("计算图形面积");
}
public void display() {
System.out.println("这是一个图形,面积:" + area);
}
}
public class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override // 注解,表示这是重写的方法
public void calculateArea() {
area = Math.PI * radius * radius;
System.out.println("计算圆形面积");
}
@Override
public void display() {
System.out.println("这是一个圆形,半径:" + radius + ",面积:" + area);
}
}
public class Rectangle extends Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public void calculateArea() {
area = width * height;
System.out.println("计算矩形面积");
}
@Override
public void display() {
System.out.println("这是一个矩形,宽:" + width + ",高:" + height + ",面积:" + area);
}
}
四、多态(Polymorphism)
4.1 多态的概念
多态允许不同类的对象对同一消息做出不同的响应:
public class PolymorphismDemo {
public static void main(String[] args) {
// 多态:父类引用指向子类对象
Animal animal1 = new Dog("旺财", 3, "金毛");
Animal animal2 = new Cat("咪咪", 2);
// 调用重写的方法,表现出不同的行为
animal1.eat(); // 输出:旺财正在吃东西
animal2.eat(); // 输出:咪咪正在优雅地吃猫粮
// 多态数组
Animal[] animals = {
new Dog("小黑", 2, "拉布拉多"),
new Cat("小白", 1),
new Dog("大黄", 4, "土狗")
};
// 统一处理不同类型的对象
for (Animal animal : animals) {
animal.showInfo();
animal.eat();
System.out.println("---");
}
}
}
4.2 instanceof 运算符
用于检查对象是否是特定类的实例:
public class InstanceofDemo {
public static void processAnimal(Animal animal) {
animal.eat(); // 多态调用
// 类型检查和向下转型
if (animal instanceof Dog) {
Dog dog = (Dog) animal; // 向下转型
dog.bark(); // 调用子类特有方法
} else if (animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.meow();
}
}
public static void main(String[] args) {
processAnimal(new Dog("旺财", 3, "金毛"));
processAnimal(new Cat("咪咪", 2));
}
}
4.3 抽象方法和抽象类
// 抽象类
public abstract class Employee {
protected String name;
protected double baseSalary;
public Employee(String name, double baseSalary) {
this.name = name;
this.baseSalary = baseSalary;
}
// 抽象方法,子类必须实现
public abstract double calculateSalary();
// 具体方法
public void showInfo() {
System.out.println("员工:" + name + ",工资:" + calculateSalary());
}
}
// 具体子类
public class FullTimeEmployee extends Employee {
private double bonus;
public FullTimeEmployee(String name, double baseSalary, double bonus) {
super(name, baseSalary);
this.bonus = bonus;
}
@Override
public double calculateSalary() {
return baseSalary + bonus;
}
}
public class PartTimeEmployee extends Employee {
private int hoursWorked;
private double hourlyRate;
public PartTimeEmployee(String name, int hoursWorked, double hourlyRate) {
super(name, 0); // 兼职员工没有基本工资
this.hoursWorked = hoursWorked;
this.hourlyRate = hourlyRate;
}
@Override
public double calculateSalary() {
return hoursWorked * hourlyRate;
}
}
五、final 关键字
5.1 final 变量
public class FinalVariableDemo {
// final 实例变量必须初始化
private final String name = "张三";
private final int id;
// final 静态变量(常量)
public static final double PI = 3.14159;
public static final String COMPANY_NAME = "ABC公司";
public FinalVariableDemo(int id) {
this.id = id; // 在构造方法中初始化 final 变量
}
public void method() {
final int localVar = 100; // final 局部变量
// localVar = 200; // 编译错误:无法修改 final 变量
System.out.println("ID: " + id + ", Name: " + name);
}
}
5.2 final 方法
public class Parent {
// final 方法不能被重写
public final void finalMethod() {
System.out.println("这是一个 final 方法");
}
public void normalMethod() {
System.out.println("这是一个普通方法");
}
}
public class Child extends Parent {
// @Override
// public void finalMethod() { // 编译错误:无法重写 final 方法
// System.out.println("尝试重写 final 方法");
// }
@Override
public void normalMethod() {
System.out.println("重写普通方法");
}
}
5.3 final 类
// final 类不能被继承
public final class FinalClass {
public void method() {
System.out.println("final 类的方法");
}
}
// public class SubClass extends FinalClass { // 编译错误:无法继承 final 类
// }
// Java 中的 final 类示例
// String、Integer、Double 等包装类都是 final 类
String str = "Hello"; // String 是 final 类
Integer num = 100; // Integer 是 final 类
六、对象的生命周期
6.1 对象的创建过程
public class ObjectLifecycle {
private String name;
private static int count = 0;
// 静态代码块:类加载时执行
static {
System.out.println("静态代码块执行");
}
// 实例代码块:每次创建对象时执行
{
System.out.println("实例代码块执行");
count++;
}
// 构造方法
public ObjectLifecycle(String name) {
System.out.println("构造方法执行");
this.name = name;
}
public static int getCount() {
return count;
}
}
// 执行顺序:静态代码块 → 实例代码块 → 构造方法
6.2 垃圾回收
public class GarbageCollectionDemo {
private String name;
public GarbageCollectionDemo(String name) {
this.name = name;
}
// finalize 方法(不推荐使用)
@Override
protected void finalize() throws Throwable {
System.out.println(name + " 对象被回收");
super.finalize();
}
public static void main(String[] args) {
GarbageCollectionDemo obj1 = new GarbageCollectionDemo("对象1");
GarbageCollectionDemo obj2 = new GarbageCollectionDemo("对象2");
obj1 = null; // 取消引用
obj2 = null;
System.gc(); // 建议进行垃圾回收(不保证立即执行)
try {
Thread.sleep(1000); // 等待垃圾回收
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
七、设计原则
7.1 单一职责原则
// 不好的设计:一个类承担多个职责
class BadEmployee {
private String name;
private double salary;
public void calculateSalary() { /* 计算工资 */ }
public void saveToDatabase() { /* 保存到数据库 */ }
public void sendEmail() { /* 发送邮件 */ }
}
// 好的设计:职责分离
class Employee {
private String name;
private double salary;
public void calculateSalary() { /* 只负责计算工资 */ }
// getter 和 setter 方法
}
class EmployeeDAO {
public void save(Employee employee) { /* 负责数据持久化 */ }
}
class EmailService {
public void sendEmail(Employee employee) { /* 负责发送邮件 */ }
}
7.2 开闭原则
// 对扩展开放,对修改关闭
abstract class Shape {
public abstract double calculateArea();
}
class Circle extends Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}
class Rectangle extends Shape {
private double width, height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double calculateArea() {
return width * height;
}
}
// 添加新图形时,不需要修改现有代码
class Triangle extends Shape {
private double base, height;
public Triangle(double base, double height) {
this.base = base;
this.height = height;
}
@Override
public double calculateArea() {
return 0.5 * base * height;
}
}
总结
面向对象编程的核心概念:
- 封装:隐藏内部实现,提供公共接口
- 继承:代码复用,建立类之间的层次关系
- 多态:同一接口,不同实现,提高代码灵活性
- 抽象:提取共同特征,定义规范
设计原则:高内聚、低耦合,遵循 SOLID 原则,编写可维护、可扩展的代码。