杰瑞科技汇

Java面向对象程序设计教程该怎么学?

Java面向对象程序设计教程

目录

  1. 前言:为什么是面向对象?
  2. 第一部分:Java OOP核心基石
    • 1 万物皆对象:类与对象
    • 2 对象的蓝图:类
    • 3 从蓝图到实例:创建对象
    • 4 对象的状态与行为:成员变量与方法
    • 5 构造方法:对象的“出厂设置”
    • 6 this关键字:指代当前对象
  3. 第二部分:OOP三大特性
    • 1 封装:隐藏细节,保护数据
    • 2 继承:代码复用与扩展
    • 3 多态:同一接口,多种形态
  4. 第三部分:面向对象进阶
    • 1 抽象类与接口
    • 2 static关键字:静态成员
    • 3 内部类
    • 4 枚举
  5. 第四部分:实战演练——设计一个简单的学生管理系统
  6. 总结与学习资源

前言:为什么是面向对象?

在过程式编程(如C语言)中,我们关注的是“怎么做”——即一系列的步骤和函数,而面向对象编程则关注的是“谁来做”——即通过对象之间的交互来完成功能。

Java面向对象程序设计教程该怎么学?-图1
(图片来源网络,侵删)

OOP的核心思想:

  • 万物皆对象:将现实世界中的事物抽象成程序中的对象。
  • 对象之间通过消息通信:一个对象通过调用另一个对象的方法来请求其服务。
  • 程序由一系列相互作用的对象组成

OOP的优势:

  • 可维护性高:代码结构清晰,易于理解和修改。
  • 可复用性强:通过继承和组合,可以复用已有的代码。
  • 可扩展性好:可以轻松地添加新功能,而无需修改大量现有代码。
  • 更贴近现实世界:建模方式自然,便于分析和设计。

第一部分:Java OOP核心基石

1 万物皆对象:类与对象

  • :是对象的模板或蓝图,它定义了一类对象共有的属性(数据)和行为(方法)。“汽车”是一个类,它定义了所有汽车都有的属性(颜色、品牌、速度)和行为(启动、加速、刹车)。
  • 对象:是类的具体实例,它是一个实实在在存在的个体,拥有类中定义的属性和行为。“我的那辆红色的特斯拉”汽车”类的一个对象。

关系:类是抽象的,对象是具体的,一个类可以创建多个对象。

2 对象的蓝图:类

在Java中,使用class关键字来定义一个类。

Java面向对象程序设计教程该怎么学?-图2
(图片来源网络,侵删)
// 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是一个引用变量,指向当前正在操作的对象,它主要用于:

Java面向对象程序设计教程该怎么学?-图3
(图片来源网络,侵删)
  1. 区分成员变量和局部变量:当方法参数与成员变量同名时,使用 this.成员变量 来访问成员变量。
  2. 调用本类的其他构造方法this() 必须放在构造方法的第一行。
public class Person {
    String name;
    public Person(String name) {
        this.name = name; // this.name 指的是成员变量 name
    }
}

第二部分:OOP三大特性

1 封装

概念:将对象的属性方法捆绑在一起,并对外部世界隐藏对象的内部细节,只暴露有限的接口(公共方法)与外部交互。

目的

  • 保护数据:防止外部代码随意修改对象内部状态。
  • 隐藏实现细节:降低模块间的耦合度,修改内部实现不影响外部调用者。

实现方式

  1. 将成员变量声明为 private(私有),使其只能在当前类内部访问。
  2. 提供公共的 public 方法来访问和修改这些私有变量,这些方法通常称为 GetterSetter
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 多态

概念:指同一个接口,使用不同的实例而执行不同操作的能力,简单说就是:“父类引用指向子类对象”

实现多态的三个必要条件

  1. 继承:必须有类之间的继承关系。
  2. 重写:子类必须重写父类的方法。
  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);
        }
    }
}

第四部分:实战演练——设计一个简单的学生管理系统

让我们用学到的知识来设计一个简单的系统。

需求:能够添加学生,并显示所有学生的信息。

步骤

  1. 定义 Student

    • 属性:id (学号), name (姓名), age (年龄)。
    • 将属性设为私有,提供Getter和Setter。
    • 重写 toString() 方法,方便打印学生信息。
  2. 定义 StudentManager

    • 属性:一个 List<Student> 用来存储所有学生。
    • 方法:
      • addStudent(Student s): 添加学生。
      • showAllStudents(): 显示所有学生信息。
  3. 编写 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的系统性认识。

学习建议

  1. 动手编码:理论学得再多,不如亲手敲一遍代码,教程中的每个例子都请自己运行并修改。
  2. 多思考“为什么”:理解每个设计背后的思想,而不仅仅是语法。
  3. 阅读优秀代码:阅读Java标准库(如 java.util 包)的源码,看看大师是如何设计的。
  4. 实践出真知:尝试设计自己的小项目,在实践中巩固知识。

推荐资源

分享:
扫描分享到社交APP
上一篇
下一篇