Java 核心与应用:Java 面向对象

目录

  • Java 核心与应用:Java 面向对象
    • 引言
    • 学习目标
    • 1. 面向对象编程的三大特性
      • 1.1 封装
        • 1.1.1 封装的实现
      • 1.2 继承
        • 1.2.1 继承的实现
      • 1.3 多态
        • 1.3.1 多态的实现
    • 2. 类与对象的关系
      • 2.1 类与对象的概念
        • 2.1.1 类与对象的关系示例
    • 3. 方法签名与重载的边界条件
      • 3.1 方法签名
        • 3.1.1 方法签名的示例
      • 3.2 方法重载的边界条件
        • 3.2.1 方法重载的边界条件示例
    • 4. 对象内存布局
      • 4.1 对象内存布局的组成
        • 4.1.1 对象内存布局的示例
      • 4.2 对象内存布局
        • 4.2.1 对象头内存布局图示
        • 4.2.2 对象内存布局的图示
    • 5. 案例程序
      • 5.1 案例程序目录结构
      • 5.2 案例程序代码
        • 5.2.1 Animal.java
        • 5.2.2 Dog.java
        • 5.2.3 Cat.java
        • 5.2.4 Person.java
        • 5.2.5 Car.java
        • 5.2.6 Calculator.java
        • 5.2.7 Main.java
        • 5.2.8 MainTest.java
    • 6. 内容扩展
      • 6.1 面向对象设计原则
      • 6.2 扩展阅读
      • 6.3 练习题
    • 7. 总结
    • 8. 分享与讨论

Java 核心与应用:Java 面向对象

引言

“面向对象编程(OOP)是一种编程范式,它使用‘对象’来设计应用程序和计算机程序。对象是类的实例,类是对现实世界实体的抽象。” —— Oracle 官方文档

在 Java 开发中,面向对象编程(OOP)是核心思想之一。掌握 OOP 不仅能够帮助你编写出结构清晰、易于维护的代码,还能让你在解决复杂问题时更加得心应手。本文将深入探讨 Java 面向对象的核心概念,包括封装、继承、多态、类与对象的关系、方法签名与重载的边界条件,以及对象内存布局等。通过丰富的案例和详细的解释,你将能够全面理解这些概念,并能够在实际开发中灵活运用。

学习目标

  1. 理解面向对象编程的三大特性:封装、继承、多态。
  2. 掌握类与对象的关系,理解模板与实例的概念。
  3. 熟悉方法签名与重载的边界条件。
  4. 了解对象内存布局,包括对象头、实例数据和对齐填充。

1. 面向对象编程的三大特性

1.1 封装

封装是面向对象编程的基石之一。它通过将数据和行为封装在一个类中,隐藏了内部实现的细节,只暴露必要的接口供外部使用。封装不仅提高了代码的安全性,还增强了代码的可维护性。

1.1.1 封装的实现
public class Person {
    private String name; // 私有属性,外部无法直接访问
    private int age;

    // 公共方法,提供对私有属性的访问
    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) { // 数据校验
            this.age = age;
        }
    }
}

关键点:

  • 使用 private 关键字将属性封装在类内部。
  • 通过 public 方法提供对私有属性的访问和修改。
封装层次 实现方式 典型场景
字段级 private访问修饰符 防止外部直接修改敏感数据
方法级 公共方法暴露操作 业务规则的内聚管理
类级 不可变对象设计 线程安全的数据传输对象

架构师提示:真正的封装应该像黑匣子,对外只暴露明确的接口契约,内部实现细节对调用方完全透明

1.2 继承

继承是面向对象编程中实现代码复用的重要机制。通过继承,子类可以继承父类的属性和方法,并可以在子类中添加新的属性和方法,或者重写父类的方法。

1.2.1 继承的实现
public class Animal {
    private String name;

    public Animal(String name) {
        this.name = name;
    }

    public void eat() {
        System.out.println(name + " is eating.");
    }
}

public class Dog extends Animal {
    public Dog(String name) {
        super(name); // 调用父类的构造方法
    }

    public void bark() {
        System.out.println("Woof! Woof!");
    }
}

关键点:

  • 使用 extends 关键字实现继承。
  • 子类可以调用父类的构造方法,使用 super 关键字。

1.3 多态

多态是指同一个方法在不同的对象中有不同的实现。多态性允许我们编写通用的代码,这些代码可以处理不同类型的对象。

1.3.1 多态的实现
public class Animal {
    public void makeSound() {
        System.out.println("Animal is making a sound.");
    }
}

public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof! Woof!");
    }
}

public class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow! 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! Meow!
    }
}

关键点:

  • 通过方法重写实现多态。
  • 父类引用指向子类对象,调用重写的方法时,实际执行的是子类的方法。

2. 类与对象的关系

2.1 类与对象的概念

类是对象的模板,对象是类的实例。类定义了对象的属性和行为,而对象则是类的具体表现。

2.1.1 类与对象的关系示例
public class Car {
    private String brand;
    private String model;

    public Car(String brand, String model) {
        this.brand = brand;
        this.model = model;
    }

    public void drive() {
        System.out.println("Driving " + brand + " " + model);
    }
}

public class Main {
    public static void main(String[] args) {
        Car myCar = new Car("Toyota", "Corolla"); // 创建 Car 类的对象
        myCar.drive(); // 输出: Driving Toyota Corolla
    }
}

关键点:

  • 类是抽象的,对象是具体的。
  • 通过 new 关键字创建类的对象。

3. 方法签名与重载的边界条件

3.1 方法签名

方法签名由方法名和参数列表组成,它是方法的唯一标识。方法签名不包括返回类型和访问修饰符。

3.1.1 方法签名的示例
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

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

关键点:

  • 方法名相同,但参数列表不同,构成方法重载。

3.2 方法重载的边界条件

方法重载是指在同一个类中,允许存在多个方法名相同但参数列表不同的方法。方法重载的边界条件包括参数的类型、数量和顺序。

3.2.1 方法重载的边界条件示例
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

    public int add(int a, int b, int c) {
        return a + b + c;
    }

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

关键点:

  • 方法重载不能仅通过返回类型来区分。
  • 参数列表必须不同,可以是类型、数量或顺序不同。

4. 对象内存布局

4.1 对象内存布局的组成

Java 对象在内存中的布局通常包括对象头、实例数据和对齐填充。

4.1.1 对象内存布局的示例
public class Person {
    private String name;
    private int age;
    private boolean isStudent;
}

关键点:

  • 对象头:包含对象的元数据,如哈希码、GC 信息、锁状态等。
  • 实例数据:对象的实际数据,即对象的属性。
  • 对齐填充:为了内存对齐而填充的字节,确保对象的大小是 8 字节的倍数。

4.2 对象内存布局

4.2.1 对象头内存布局图示

HotSpot 对象结构:
64位JVM对象头结构:

|---------------------------------------------------|
| Mark Word (64bits)           | Klass Pointer (32bits) |
|---------------------------------------------------|
| 实例数据区                                      |
|---------------------------------------------------|
| 对齐填充 (保证对象大小是8字节的倍数)              |
|---------------------------------------------------|

对象头Mark Word内容(无锁状态):

|------------------------------|-------------------|
| 对象哈希码 (31bits)           | 分代年龄 (4bits)  |
|------------------------------|-------------------|
| 锁标志位 (2bits)              | 未使用 (1bit)     |
|------------------------------|-------------------|
4.2.2 对象内存布局的图示
+-------------------+
|     对象头        |
+-------------------+
|   实例数据        |
|   - name (String) |
|   - age (int)     |
|   - isStudent (boolean) |
+-------------------+
|   对齐填充        |
+-------------------+

关键点:

  • 对象头的大小通常是 12 字节(32 位 JVM)或 16 字节(64 位 JVM)。
  • 实例数据的大小取决于对象的属性类型和数量。
  • 对齐填充是为了优化内存访问速度。

5. 案例程序

5.1 案例程序目录结构

src
├── main
│   ├── java
│   │   ├── com
│   │   │   ├── example
│   │   │   │   ├── Animal.java
│   │   │   │   ├── Dog.java
│   │   │   │   ├── Cat.java
│   │   │   │   ├── Person.java
│   │   │   │   ├── Car.java
│   │   │   │   ├── Calculator.java
│   │   │   │   └── Main.java
│   └── resources
└── test
    └── java
        └── com
            └── example
                └── MainTest.java

关键点:

  • src/main/java 存放主程序代码。
  • src/test/java 存放测试代码。

5.2 案例程序代码

5.2.1 Animal.java
package com.example;

public class Animal {
    public void makeSound() {
        System.out.println("Animal is making a sound.");
    }
}
5.2.2 Dog.java
package com.example;

public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Woof! Woof!");
    }
}
5.2.3 Cat.java
package com.example;

public class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Meow! Meow!");
    }
}
5.2.4 Person.java
package com.example;

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

    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) {
            this.age = age;
        }
    }
}
5.2.5 Car.java
package com.example;

public class Car {
    private String brand;
    private String model;

    public Car(String brand, String model) {
        this.brand = brand;
        this.model = model;
    }

    public void drive() {
        System.out.println("Driving " + brand + " " + model);
    }
}
5.2.6 Calculator.java
package com.example;

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

    public int add(int a, int b, int c) {
        return a + b + c;
    }

    public double add(double a, double b) {
        return a + b;
    }
}
5.2.7 Main.java
package com.example;

public class Main {
    public static void main(String[] args) {
        // 多态示例
        Animal myDog = new Dog();
        Animal myCat = new Cat();

        myDog.makeSound(); // 输出: Woof! Woof!
        myCat.makeSound(); // 输出: Meow! Meow!

        // 类与对象示例
        Car myCar = new Car("Toyota", "Corolla");
        myCar.drive(); // 输出: Driving Toyota Corolla

        // 方法重载示例
        Calculator calc = new Calculator();
        System.out.println(calc.add(1, 2)); // 输出: 3
        System.out.println(calc.add(1, 2, 3)); // 输出: 6
        System.out.println(calc.add(1.5, 2.5)); // 输出: 4.0
    }
}
5.2.8 MainTest.java
package com.example;

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class MainTest {
    @Test
    public void testAdd() {
        Calculator calc = new Calculator();
        assertEquals(3, calc.add(1, 2));
        assertEquals(6, calc.add(1, 2, 3));
        assertEquals(4.0, calc.add(1.5, 2.5));
    }
}

关键点:

  • 使用 JUnit 进行单元测试,确保代码的正确性。

6. 内容扩展

6.1 面向对象设计原则

除了封装、继承、多态,面向对象设计还有五大原则,即 SOLID 原则:

  1. 单一职责原则(SRP):一个类应该只有一个引起它变化的原因。
  2. 开放-封闭原则(OCP):软件实体应该对扩展开放,对修改封闭。
  3. 里氏替换原则(LSP):子类应该能够替换父类并且不影响程序的正确性。
  4. 接口隔离原则(ISP):客户端不应该依赖它不需要的接口。
  5. 依赖倒置原则(DIP):高层模块不应该依赖低层模块,二者都应该依赖抽象。

6.2 扩展阅读

  • Oracle 官方 Java 文档
  • Spring Framework 官方指南
  • 《Effective Java》 by Joshua Bloch
  • 《Java 编程思想》 by Bruce Eckel

6.3 练习题

  1. 设计一个 BankAccount 类,包含 depositwithdraw 方法,并实现封装。
  2. 创建一个 Shape 类,并派生出 CircleRectangle 子类,实现多态。
  3. 编写一个 Calculator 类,实现加减乘除方法的重载。

7. 总结

通过本文的学习,你应该已经掌握了 Java 面向对象编程的核心概念,包括封装、继承、多态、类与对象的关系、方法签名与重载的边界条件,以及对象内存布局。这些知识不仅能够帮助你编写出高质量的代码,还能让你在解决复杂问题时更加得心应手。希望你能在实际开发中灵活运用这些知识,不断提升自己的开发技能。

8. 分享与讨论

“学习是一个不断探索和实践的过程。如果你有任何问题或想法,欢迎在评论区分享,我们一起讨论,共同进步!”

分享到知乎 | 分享到掘金 | 分享到微博 | 分享到 QQ | 分享到 Stack Overflow

#Java全栈开发 #SpringBoot实战 #JVM调优 #微服务架构 #Java21虚拟线程实战 #GraalVM云原生实践 #电商秒杀系统设计


期待与你相遇!

如果你对编程充满热情,想获取丰富的编程学习资料,如经典编程书籍、实用教程等,欢迎加入我们的大家庭!点击云盘链接获取入群方式,扫码添加入群,即可领取海量编程资源!一起提升技能,开启你的编程进阶之旅!


上一篇:Java 流程控制语句
下一篇:Java 类的定义与使用

你可能感兴趣的:(《Java,核心与应用》,java,python,开发语言)