Java面向对象编程:类与对象详解

39 阅读6分钟

1. 类与对象基础

类的定义与结构

类是Java面向对象编程的核心概念,用于描述具有相同特征和行为的一组对象。类定义了对象的属性(成员变量)和行为(方法)。

java

// 学生类的定义
public class Student {
    // 成员变量(属性)
    public int age;
    public String name;
    public int id;
    
    // 成员方法(行为)
    public void eat() {
        System.out.println(name + "正在吃饭");
    }
    
    public void study() {
        System.out.println(name + "正在学习");
    }
}

对象的实例化与使用

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

java

public class Test {
    public static void main(String[] args) {
        // 创建学生对象
        Student student1 = new Student();
        
        // 设置对象属性
        student1.name = "小明";
        student1.age = 18;
        student1.id = 20024943;
        
        // 访问对象属性和方法
        System.out.println("姓名: " + student1.name);
        System.out.println("年龄: " + student1.age);
        System.out.println("学号: " + student1.id);
        
        // 调用对象方法
        student1.eat();
        student1.study();
    }
}

2. this关键字详解

this的作用与使用场景

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

java

public class Date {
    public int year;
    public int month;
    public int day;
    
    // 不使用this会导致参数遮蔽问题
    public void setYear(int year) {
        // year = year;  // 错误:参数遮蔽了成员变量
        this.year = year; // 正确:使用this明确指定成员变量
    }
    
    public int getYear() {
        return this.year; // 明确返回当前对象的year
    }
    
    // this调用其他构造方法
    public Date() {
        this(2024, 1, 1); // 调用带参数的构造方法
    }
    
    public Date(int year, int month, int day) {
        this.year = year;
        this.month = month;
        this.day = day;
    }
}

测试示例

java

public class TestDate {
    public static void main(String[] args) {
        Date date = new Date();
        date.setYear(2005);
        System.out.println("年份: " + date.getYear()); // 正确输出: 2005
    }
}

3. 构造方法深入理解

构造方法的特性与使用

构造方法用于在创建对象时初始化对象的状态:

java

public class Student {
    public int age;
    public String name;
    public int id;
    
    // 默认构造方法
    public Student() {
        // 编译器会自动提供默认构造方法
        // 但如果定义了带参构造方法,需要显式定义无参构造方法
    }
    
    // 带参构造方法
    public Student(int age, String name, int id) {
        this.age = age;
        this.name = name;
        this.id = id;
    }
    
    // 构造方法重载
    public Student(String name) {
        this(18, name, 0); // 调用其他构造方法
    }
    
    // toString方法重写
    @Override
    public String toString() {
        return name + " 年龄" + age + " 学号" + id;
    }
    
    public void eat() {
        System.out.println(name + "正在吃饭");
    }
    
    public void study() {
        System.out.println(name + "正在学习");
    }
}

构造方法使用示例

java

public class TestStudent {
    public static void main(String[] args) {
        // 使用不同构造方法创建对象
        Student student1 = new Student(18, "小明", 2300450);
        Student student2 = new Student(19, "李华", 2300134);
        Student student3 = new Student("张三");
        
        // 直接输出对象(调用toString方法)
        System.out.println(student1);
        System.out.println(student2);
        System.out.println(student3);
        
        // 调用对象方法
        student1.study();
        student2.eat();
    }
}

4. 封装与访问控制

封装的概念与实现

封装是面向对象的三大特性之一,通过访问修饰符控制对类成员的访问:

java

public class Dog {
    // 使用private实现封装
    private int age;
    private String name;
    private String breed;
    
    // 构造方法
    public Dog(int age, String name, String breed) {
        this.age = age;
        this.name = name;
        this.breed = breed;
    }
    
    // Getter方法 - 提供读取权限
    public String getName() {
        return name;
    }
    
    public int getAge() {
        return age;
    }
    
    public String getBreed() {
        return breed;
    }
    
    // Setter方法 - 提供修改权限(可添加验证逻辑)
    public void setName(String name) {
        if (name != null && !name.trim().isEmpty()) {
            this.name = name;
        } else {
            System.out.println("姓名不能为空");
        }
    }
    
    public void setAge(int age) {
        if (age >= 0 && age <= 30) {
            this.age = age;
        } else {
            System.out.println("年龄必须在0-30之间");
        }
    }
    
    // 业务方法
    public void bark() {
        System.out.println(name + "在汪汪叫");
    }
    
    public void displayInfo() {
        System.out.println("品种: " + breed + ", 姓名: " + name + ", 年龄: " + age);
    }
}

封装测试示例

java

public class TestDog {
    public static void main(String[] args) {
        Dog myDog = new Dog(3, "旺财", "金毛");
        
        // 通过公共方法访问私有属性
        myDog.displayInfo();
        myDog.bark();
        
        // 修改属性(通过setter验证)
        myDog.setAge(4);
        myDog.setName(""); // 会触发验证警告
        
        // 直接访问私有属性会编译错误
        // myDog.age = 5; // 错误: age 在 Dog 中是 private 访问控制
    }
}

5. 包(Package)与导入(Import)

包的组织结构

包用于组织相关的类,避免命名冲突:

text

项目结构:
src/
├── com/
│   └── animal/
│       ├── Dog.java
│       └── Cat.java
└── com/
    └── test/
        └── TestAnimal.java

包的定义与使用

java

// Dog.java - 在com.animal包中
package com.animal;

public class Dog {
    private String name;
    
    public Dog(String name) {
        this.name = name;
    }
    
    public void bark() {
        System.out.println(name + "在叫");
    }
}

java

// TestAnimal.java - 在com.test包中
package com.test;

import com.animal.Dog;  // 导入特定类
// import com.animal.*; // 导入整个包

public class TestAnimal {
    public static void main(String[] args) {
        Dog dog = new Dog("Buddy");
        dog.bark();
    }
}

6. static关键字详解

静态成员的特点

静态成员属于类而不是对象,在类加载时初始化:

java

public class Student {
    // 实例变量 - 每个对象独立拥有
    private String name;
    private int age;
    
    // 静态变量 - 所有对象共享
    private static String school = "某某大学";
    private static int studentCount = 0;
    
    // 构造方法
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        studentCount++; // 每次创建对象时计数增加
    }
    
    // 实例方法 - 可以访问静态和非静态成员
    public void displayInfo() {
        System.out.println("姓名: " + name + ", 年龄: " + age + ", 学校: " + school);
    }
    
    // 静态方法 - 只能访问静态成员
    public static void displaySchoolInfo() {
        System.out.println("学校名称: " + school);
        System.out.println("学生总数: " + studentCount);
        // System.out.println(name); // 错误:不能访问非静态成员
    }
    
    // 静态代码块 - 类加载时执行
    static {
        System.out.println("Student类被加载");
        // 可以在这里进行静态变量的复杂初始化
    }
    
    // Getter和Setter
    public static String getSchool() {
        return school;
    }
    
    public static void setSchool(String school) {
        Student.school = school;
    }
    
    public static int getStudentCount() {
        return studentCount;
    }
}

static使用示例

java

public class TestStatic {
    public static void main(String[] args) {
        // 通过类名访问静态方法和变量
        Student.displaySchoolInfo();
        System.out.println("学校: " + Student.getSchool());
        
        // 创建对象
        Student stu1 = new Student("张三", 20);
        Student stu2 = new Student("李四", 21);
        
        // 通过对象访问静态方法(不推荐)
        stu1.displaySchoolInfo();
        
        // 通过类名访问(推荐)
        Student.displaySchoolInfo();
        
        // 修改静态变量会影响所有对象
        Student.setSchool("新大学");
        stu1.displayInfo();
        stu2.displayInfo();
    }
}

7. 初始化顺序总结

类加载与对象创建的执行顺序

java

public class InitOrderDemo {
    // 静态变量
    private static String staticField = "静态变量";
    
    // 静态代码块
    static {
        System.out.println(staticField);
        System.out.println("静态代码块");
    }
    
    // 实例变量
    private String instanceField = "实例变量";
    
    // 实例代码块
    {
        System.out.println(instanceField);
        System.out.println("实例代码块");
    }
    
    // 构造方法
    public InitOrderDemo() {
        System.out.println("构造方法");
    }
    
    public static void main(String[] args) {
        System.out.println("main方法开始");
        new InitOrderDemo();
        System.out.println("main方法结束");
    }
}

执行结果

text

静态变量
静态代码块
main方法开始
实例变量
实例代码块
构造方法
main方法结束

核心概念总结

面向对象编程要点

  1. 类与对象:类是蓝图,对象是具体实例
  2. 封装:通过访问修饰符控制对类成员的访问
  3. 构造方法:用于对象初始化,支持重载
  4. this关键字:引用当前对象,解决命名冲突
  5. static关键字:类级别成员,所有对象共享
  6. 包机制:组织代码,避免命名冲突

最佳实践建议

  1. 合理使用访问修饰符,优先使用private
  2. 为类提供完整的getter和setter方法
  3. 合理使用构造方法重载
  4. 静态方法中不要访问非静态成员
  5. 使用包来组织相关的类
  6. 遵循Java命名规范

这些面向对象的基础概念为后续学习继承、多态等高级特性奠定了重要基础。建议通过实际编码练习来加深理解。