跳转至

类与对象

类和对象是面向对象编程的核心概念。类是对象的模板或蓝图,对象是类的实例。理解类和对象的关系是掌握Java面向对象编程的基础。

类的概念

类(Class)是一种用户定义的数据类型,它描述了一组对象的共同特征和行为。类定义了对象的属性(字段)和方法。

类的基本结构

public class ClassName {
    // 字段(属性)
    private dataType fieldName;

    // 构造方法
    public ClassName() {
        // 初始化代码
    }

    // 方法
    public returnType methodName() {
        // 方法体
        return value;
    }
}

简单的类定义示例

public class Student {
    // 字段(实例变量)
    private String name;
    private int age;
    private String studentId;
    private double score;

    // 构造方法
    public Student() {
        // 默认构造方法
    }

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

    // 方法
    public void study() {
        System.out.println(name + " 正在学习");
    }

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

    public void displayInfo() {
        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) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

对象的创建和使用

对象是类的实例,通过 new 关键字创建。

创建对象

public class StudentTest {
    public static void main(String[] args) {
        // 使用默认构造方法创建对象
        Student student1 = new Student();

        // 使用带参数的构造方法创建对象
        Student student2 = new Student("张三", 20, "2023001");

        // 设置student1的属性
        student1.setName("李四");
        student1.setAge(19);

        // 调用对象的方法
        student1.study();
        student1.takeExam(85.5);
        student1.displayInfo();

        System.out.println("---");

        student2.study();
        student2.takeExam(92.0);
        student2.displayInfo();
    }
}

对象的内存分配

public class ObjectMemory {
    public static void main(String[] args) {
        // 创建对象时的内存分配
        Student s1 = new Student("王五", 21, "2023002");
        Student s2 = new Student("赵六", 22, "2023003");
        Student s3 = s1; // s3和s1指向同一个对象

        System.out.println("s1的姓名: " + s1.getName());
        System.out.println("s3的姓名: " + s3.getName());

        // 通过s3修改对象
        s3.setName("王五五");

        System.out.println("修改后:");
        System.out.println("s1的姓名: " + s1.getName()); // 也会改变
        System.out.println("s3的姓名: " + s3.getName());

        // 对象比较
        System.out.println("s1 == s2: " + (s1 == s2)); // false,不同对象
        System.out.println("s1 == s3: " + (s1 == s3)); // true,同一对象
    }
}

字段(属性)

字段是类中定义的变量,用于存储对象的状态信息。

实例字段

每个对象都有自己的实例字段副本。

public class Car {
    // 实例字段
    private String brand;      // 品牌
    private String model;      // 型号
    private int year;          // 年份
    private double price;      // 价格
    private boolean isRunning; // 是否在运行

    public Car(String brand, String model, int year, double price) {
        this.brand = brand;
        this.model = model;
        this.year = year;
        this.price = price;
        this.isRunning = false; // 默认不在运行
    }

    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("车辆已经停止");
        }
    }

    // Getter方法
    public String getBrand() { return brand; }
    public String getModel() { return model; }
    public int getYear() { return year; }
    public double getPrice() { return price; }
    public boolean isRunning() { return isRunning; }
}

类字段(静态字段)

类字段属于类本身,被所有实例共享。

public class Counter {
    // 类字段(静态字段)
    private static int totalCount = 0;
    public static final String COMPANY_NAME = "ABC公司";

    // 实例字段
    private int instanceId;
    private String name;

    public Counter(String name) {
        this.name = name;
        totalCount++;           // 每创建一个实例,总数加1
        this.instanceId = totalCount;
    }

    // 静态方法
    public static int getTotalCount() {
        return totalCount;
    }

    // 实例方法
    public void displayInfo() {
        System.out.println("实例ID: " + instanceId);
        System.out.println("名称: " + name);
        System.out.println("总实例数: " + totalCount);
        System.out.println("公司名称: " + COMPANY_NAME);
    }
}

// 使用示例
public class CounterTest {
    public static void main(String[] args) {
        System.out.println("初始总数: " + Counter.getTotalCount());

        Counter c1 = new Counter("计数器1");
        Counter c2 = new Counter("计数器2");
        Counter c3 = new Counter("计数器3");

        c1.displayInfo();
        System.out.println("---");
        c2.displayInfo();
        System.out.println("---");
        c3.displayInfo();

        System.out.println("最终总数: " + Counter.getTotalCount());
    }
}

方法

方法定义了对象的行为,是类中的函数。

实例方法

实例方法属于对象实例,可以访问实例字段和静态字段。

public class Calculator {
    private double result;

    public Calculator() {
        this.result = 0.0;
    }

    // 实例方法
    public void add(double value) {
        result += value;
    }

    public void subtract(double value) {
        result -= value;
    }

    public void multiply(double value) {
        result *= value;
    }

    public void divide(double value) {
        if (value != 0) {
            result /= value;
        } else {
            System.out.println("错误:除数不能为零");
        }
    }

    public void clear() {
        result = 0.0;
    }

    public double getResult() {
        return result;
    }

    public void displayResult() {
        System.out.println("当前结果: " + result);
    }
}

静态方法

静态方法属于类本身,不能访问实例字段,只能访问静态字段。

public class MathUtils {
    // 静态常量
    public static final double PI = 3.14159265359;

    // 静态方法
    public static int add(int a, int b) {
        return a + b;
    }

    public static double add(double a, double b) {
        return a + b;
    }

    public static int max(int a, int b) {
        return (a > b) ? a : b;
    }

    public static int max(int a, int b, int c) {
        return max(max(a, b), c);
    }

    public static double circleArea(double radius) {
        return PI * radius * radius;
    }

    public static boolean isPrime(int number) {
        if (number <= 1) return false;
        if (number <= 3) return true;
        if (number % 2 == 0 || number % 3 == 0) return false;

        for (int i = 5; i * i <= number; i += 6) {
            if (number % i == 0 || number % (i + 2) == 0) {
                return false;
            }
        }
        return true;
    }
}

// 使用示例
public class MathUtilsTest {
    public static void main(String[] args) {
        // 调用静态方法,不需要创建对象
        int sum = MathUtils.add(10, 20);
        System.out.println("10 + 20 = " + sum);

        double area = MathUtils.circleArea(5.0);
        System.out.println("半径为5的圆面积: " + area);

        int maximum = MathUtils.max(15, 25, 35);
        System.out.println("15, 25, 35的最大值: " + maximum);

        boolean isPrime = MathUtils.isPrime(17);
        System.out.println("17是质数吗? " + isPrime);
    }
}

构造方法

构造方法是特殊的方法,用于初始化对象。

默认构造方法

public class Person {
    private String name;
    private int age;

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

    public void displayInfo() {
        System.out.println("姓名: " + name + ", 年龄: " + age);
    }

    // Setter方法
    public void setName(String name) { this.name = name; }
    public void setAge(int age) { this.age = age; }
}

带参数的构造方法

public class Book {
    private String title;
    private String author;
    private double price;
    private int pages;

    // 带参数的构造方法
    public Book(String title, String author, double price, int pages) {
        this.title = title;
        this.author = author;
        this.price = price;
        this.pages = pages;
        System.out.println("创建书籍: " + title);
    }

    // 重载构造方法
    public Book(String title, String author) {
        this(title, author, 0.0, 0); // 调用其他构造方法
        System.out.println("使用简化构造方法");
    }

    public Book(String title) {
        this(title, "未知作者"); // 调用其他构造方法
    }

    public void displayInfo() {
        System.out.println("书名: " + title);
        System.out.println("作者: " + author);
        System.out.println("价格: " + price);
        System.out.println("页数: " + pages);
    }

    // Getter方法
    public String getTitle() { return title; }
    public String getAuthor() { return author; }
    public double getPrice() { return price; }
    public int getPages() { return pages; }
}

// 使用示例
public class BookTest {
    public static void main(String[] args) {
        Book book1 = new Book("Java编程思想", "Bruce Eckel", 89.0, 880);
        Book book2 = new Book("设计模式", "GoF");
        Book book3 = new Book("算法导论");

        book1.displayInfo();
        System.out.println("---");
        book2.displayInfo();
        System.out.println("---");
        book3.displayInfo();
    }
}

this 关键字

this 关键字引用当前对象实例。

this 的用法

public class Employee {
    private String name;
    private int id;
    private double salary;
    private String department;

    public Employee(String name, int id, double salary, String department) {
        // 使用this区分参数和字段
        this.name = name;
        this.id = id;
        this.salary = salary;
        this.department = department;
    }

    // 使用this调用其他构造方法
    public Employee(String name, int id) {
        this(name, id, 0.0, "未分配"); // 必须是第一行
    }

    public Employee(String name) {
        this(name, 0);
    }

    // 使用this返回当前对象(方法链)
    public Employee setName(String name) {
        this.name = name;
        return this;
    }

    public Employee setSalary(double salary) {
        this.salary = salary;
        return this;
    }

    public Employee setDepartment(String department) {
        this.department = department;
        return this;
    }

    // 将当前对象作为参数传递
    public void compareWith(Employee other) {
        if (this.salary > other.salary) {
            System.out.println(this.name + " 的薪水比 " + other.name + " 高");
        } else if (this.salary < other.salary) {
            System.out.println(this.name + " 的薪水比 " + other.name + " 低");
        } else {
            System.out.println(this.name + " 和 " + other.name + " 的薪水相同");
        }
    }

    public void displayInfo() {
        System.out.println("员工信息:");
        System.out.println("姓名: " + this.name);
        System.out.println("ID: " + this.id);
        System.out.println("薪水: " + this.salary);
        System.out.println("部门: " + this.department);
    }

    // Getter方法
    public String getName() { return this.name; }
    public int getId() { return this.id; }
    public double getSalary() { return this.salary; }
    public String getDepartment() { return this.department; }
}

// 使用示例
public class EmployeeTest {
    public static void main(String[] args) {
        Employee emp1 = new Employee("张三", 1001, 8000, "开发部");
        Employee emp2 = new Employee("李四", 1002);

        // 方法链调用
        emp2.setName("李四四")
            .setSalary(7500)
            .setDepartment("测试部");

        emp1.displayInfo();
        System.out.println("---");
        emp2.displayInfo();
        System.out.println("---");

        emp1.compareWith(emp2);
    }
}

访问修饰符

访问修饰符控制类、字段和方法的可见性。

修饰符 同一类 同一包 子类 不同包
public
protected
默认(package)
private
public class AccessModifierExample {
    public String publicField = "公共字段";
    protected String protectedField = "受保护字段";
    String packageField = "包字段";
    private String privateField = "私有字段";

    public void publicMethod() {
        System.out.println("公共方法");
        // 在同一类中可以访问所有字段
        System.out.println(publicField);
        System.out.println(protectedField);
        System.out.println(packageField);
        System.out.println(privateField);
    }

    protected void protectedMethod() {
        System.out.println("受保护方法");
    }

    void packageMethod() {
        System.out.println("包方法");
    }

    private void privateMethod() {
        System.out.println("私有方法");
    }

    public void testAccess() {
        // 在同一类中可以调用所有方法
        publicMethod();
        protectedMethod();
        packageMethod();
        privateMethod();
    }
}

类的最佳实践

1. 封装原则

public class BankAccount {
    private String accountNumber;
    private double balance;
    private String ownerName;

    public BankAccount(String accountNumber, String ownerName) {
        this.accountNumber = accountNumber;
        this.ownerName = ownerName;
        this.balance = 0.0;
    }

    // 提供安全的访问方法
    public boolean deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            System.out.println("存款成功,当前余额: " + balance);
            return true;
        } else {
            System.out.println("存款金额必须大于0");
            return false;
        }
    }

    public boolean withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            System.out.println("取款成功,当前余额: " + balance);
            return true;
        } else {
            System.out.println("取款失败:金额无效或余额不足");
            return false;
        }
    }

    // 只提供必要的getter方法
    public double getBalance() {
        return balance;
    }

    public String getAccountNumber() {
        return accountNumber;
    }

    public String getOwnerName() {
        return ownerName;
    }
}

2. 单一职责原则

// 好的设计:每个类只负责一个职责
public class Student {
    private String name;
    private String studentId;
    private int age;

    // 构造方法和基本的getter/setter
    public Student(String name, String studentId, int age) {
        this.name = name;
        this.studentId = studentId;
        this.age = age;
    }

    // 基本信息相关方法
    public String getName() { return name; }
    public String getStudentId() { return studentId; }
    public int getAge() { return age; }
}

public class Grade {
    private String studentId;
    private String subject;
    private double score;

    public Grade(String studentId, String subject, double score) {
        this.studentId = studentId;
        this.subject = subject;
        this.score = score;
    }

    // 成绩相关方法
    public String getStudentId() { return studentId; }
    public String getSubject() { return subject; }
    public double getScore() { return score; }

    public String getGradeLevel() {
        if (score >= 90) return "A";
        else if (score >= 80) return "B";
        else if (score >= 70) return "C";
        else if (score >= 60) return "D";
        else return "F";
    }
}

3. 不可变对象

public final class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() { return x; }
    public int getY() { return y; }

    // 返回新对象而不是修改当前对象
    public Point move(int deltaX, int deltaY) {
        return new Point(x + deltaX, y + deltaY);
    }

    @Override
    public String toString() {
        return "Point(" + x + ", " + y + ")";
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Point point = (Point) obj;
        return x == point.x && y == point.y;
    }

    @Override
    public int hashCode() {
        return 31 * x + y;
    }
}

类和对象是Java面向对象编程的基础。通过合理设计类的结构、正确使用访问修饰符、遵循封装原则,可以创建出高质量、易维护的代码。记住要让类的职责单一、接口简洁、实现细节隐藏。