08-从过程到对象!Java OOP核心:类与对象

0 阅读7分钟

一、【核心概念/问题引入】

1.1 先搞懂核心:面向对象到底是什么?

把面向对象比作洗衣机洗衣服,一秒就懂了:
面向过程会将任务拆解成一系列的步骤(函数),1、打开洗衣机>2、放衣服…>3、放洗衣粉…>4、启动>5、烘干
面向对象会拆出人和洗衣机两个对象:
人:打开洗衣机、放衣服、放洗衣粉
洗衣机:清洗烘干
官方定义是:面向对象编程是一种编程思想,它将现实世界中的事物抽象为「对象」,通过对象之间的交互来完成任务,而不是像面向过程那样按照步骤执行。

1.2 为什么需要面向对象?

  • 没有面向对象:代码难以维护,修改一个功能需要改很多地方,容易出错
  • 有了面向对象:代码更模块化,可复用性更高,修改和扩展都更方便

二、【核心知识点详解】

2.1 类和对象:面向对象的核心基石

是什么

  • 类(Class):是一个抽象的模板/蓝图/设计图,用来定义「某一类东西」的共同特征和行为
  • 对象(Object):是类造出来的具体、实实在在的个体,也叫「类的实例」
    怎么用
  • 定义类:class 类名 { 属性; 方法; }
  • 创建对象:类名 对象名 = new 类名();
  • 使用对象:对象名.属性对象名.方法()
    注意事项
  • 类是抽象的,不占内存;对象是具体的,在内存里真实存在
  • 一个类可以创建无数个对象
  • 没有类就没有对象
    代码示例
// 定义类
class Cat {  
    // 属性:姓名、年龄、颜色  
    String name;  
    String color;  
    int age;  
    // 方法:猫的行为  
    public void eat() {  
        System.out.println(name + " 喜欢吃鱼🐟");  
    }  
    public void run() {  
        System.out.println(name + "跑了🏃‍♂️");  
    }  
}
// 创建对象
Cat daHuang = new Cat();
// 使用对象
daHuang.name = "大黄";
daHuang.color = "黄色";
daHuang.age = 2;
daHuang.eat(); // 输出:大黄 喜欢吃鱼🐟
daHuang.run(); // 输出:大黄跑了🏃‍♂️

2.2 Java 对象在内存中的执行流程

是什么:Java 对象从创建到使用的完整内存变化过程。
内存区域

  • 栈内存:存储对象的引用变量、基本数据类型
  • 堆内存:存储真正的对象本身
  • 方法区:存储类的模板(属性、方法)
    执行流程
  1. 加载类模板:JVM 读取类的模板,存到方法区
  2. 栈内存声明引用:创建引用变量,指向 null
  3. 堆内存创建对象:分配空间,赋默认值,分配地址
  4. 给对象属性赋值:通过地址找到对象,修改值
  5. 调用对象方法:通过引用找到对象,执行方法
    注意事项
  • 栈里只有地址,没有真实数据
  • 堆里才是真实的对象,存着属性值
  • 所有方法都存在方法区,所有对象共用一套方法

2.3 成员变量和局部变量的区别

image.png
代码示例

class Test {  
    // 成员变量  
    int memberVar;  
    
    public void testMethod() {  
        // 局部变量  
        int localVar = 10;  
        System.out.println(memberVar); // 输出 0(默认值)  
        System.out.println(localVar);  // 输出 10  
    }  
}

2.4 this 关键字

是什么this 代表「当前正在调用方法的那个对象」的引用。
核心作用

  1. 解决成员变量和局部变量重名this.变量名 强制访问成员变量
  2. 调用本类的成员方法this.方法名(),通常可省略 this
  3. 调用本类的构造方法this(参数),必须在构造方法的第一行
  4. 把当前对象作为参数传递showCat(this)
    注意事项
  • static 方法里绝对不能用 this
  • this() 调用构造方法必须在第一行
  • 重名时 this 不能省略,非重名时可省略
  • this 代表对象,不是类
    代码示例
class Cat {  
    String name;  
    int age;  
    // 无参构造:用this调用有参构造  
    public Cat() {  
        this("无名小猫", 0);  
    }  
    // 有参构造:用this解决重名  
    public Cat(String name, int age) {  
        this.name = name;  
        this.age = age;  
    }  
    // setName方法:用this解决重名  
    public void setName(String name) {  
        this.name = name;  
    }  
}

2.5 构造方法

是什么:构造方法是 Java 类里一种特殊的方法,专门用来创建对象。
格式

public 类名(参数列表) { 
    // 方法体:给对象的成员变量赋值、做初始化操作 
}

核心要求

  1. 方法名必须和类名完全一致(包括大小写)
  2. 没有返回值类型(连 void 都不能写)
  3. 可以带参数,也可以不带参数
    作用
  • 创建对象:执行 new 类名() 时自动调用
  • 初始化对象属性:创建对象时给成员变量赋初始值
    注意事项
  • 如果没有手动写构造方法,Java 会自动生成一个空的无参构造
  • 一旦手动写了构造方法,Java 就不再自动生成默认无参构造
  • 构造方法支持重载
  • 构造方法不能被对象手动调用
  • 构造方法不能被继承
    代码示例
class Cat {  
    // 1. 无参构造方法(没有参数)  
    public Cat() {  
        System.out.println("无参构造被调用了!");  
    }  
    // 2. 有参构造方法(带参数)  
    public Cat(String name, int age) {  
        this.name = name;  
        this.age = age;  
        System.out.println("有参构造被调用了!");  
    }  
    // 成员变量  
    String name;  
    int age;  
}

2.6 灵魂拷问:为什么要使用面向对象?

"学到这你可能有疑问:面向对象看起来比面向过程复杂,为什么还要使用它?"
原因是:

  1. 可维护性:代码模块化,修改一个功能不会影响其他部分
  2. 可复用性:类可以被多次实例化,代码可以重复使用
  3. 可扩展性:可以通过继承、多态等特性轻松扩展功能
  4. 更符合现实世界:现实世界中的事物本来就是对象,面向对象更贴近我们的思维方式

三、【实战案例】

3.1 案例 1:手机类的设计与使用

需求描述:设计一个手机类,包含品牌、颜色、价格等属性,以及打电话、发短信等方法。
代码实现

public class Phone {  
    String brand;  
    String color;  
    double price;  
    public void call() {  
        System.out.println("用" + brand + "颜色为" + color + ",价格为" + price + ",可以给打电话");  
    }  
    
    public void sendMessage() {  
        System.out.println("用" + brand + "颜色为" + color + ",价格为" + price + ",可以群发短信");  
    }  
}
public class PhoneTest {  
    public static void main(String[] args) {  
        // 创建两个手机对象  
        Phone huawei = new Phone();  
        huawei.brand = "华为";  
        huawei.color = "极夜紫";  
        huawei.price = 5999.0;  
        huawei.call();  
        huawei.sendMessage();  
        System.out.println("==================");  
        Phone xiaomi = new Phone();  
        xiaomi.brand = "小米";  
        xiaomi.color = "冷翠银";  
        xiaomi.price = 4999;  
        xiaomi.call();  
        xiaomi.sendMessage();  
    }  
}

运行结果

用华为颜色为极夜紫,价格为5999.0,可以给打电话
用华为颜色为极夜紫,价格为5999.0,可以群发短信
==================
用小米颜色为冷翠银,价格为4999.0,可以给打电话
用小米颜色为冷翠银,价格为4999.0,可以群发短信

3.2 案例 2:使用 this 关键字和构造方法

需求描述:设计一个猫类,使用构造方法初始化属性,使用 this 关键字解决重名问题。
代码实现

class Cat {  
    String name;  
    int age;  
    // 无参构造:用this调用有参构造  
    public Cat() {  
        this("无名小猫", 0);  
    }  
    // 有参构造:用this解决重名  
    public Cat(String name, int age) {  
        this.name = name;  
        this.age = age;  
    }  
    // setName方法:用this解决重名  
    public void setName(String name) {  
        this.name = name;  
    }  
    // 调用本类成员方法  
    public void eat() {  
        System.out.println(this.name + "喜欢吃鱼🐟");  
        this.run();  
    }  
    public void run() {  
        System.out.println(this.name + "跑起来了!");  
    }  
}
public class CatTest {  
    public static void main(String[] args) {  
        // 1. 测试无参构造+this调用有参  
        Cat cat1 = new Cat();  
        cat1.eat();  
        System.out.println("==========");  
        // 2. 测试有参构造+this解决重名  
        Cat daHuang = new Cat("大黄", 2);  
        daHuang.eat();  
        System.out.println("==========");  
        // 3. 测试setName+this解决重名  
        daHuang.setName("大橘");  
        daHuang.eat();  
    }  
}

运行结果

无名小猫喜欢吃鱼🐟
无名小猫跑起来了!
==========
大黄喜欢吃鱼🐟
大黄跑起来了!
==========
大橘喜欢吃鱼🐟
大橘跑起来了!

四、【避坑指南/常见问题】

⚠️ 坑点 1:构造方法没有写对格式

错误写法

class Cat {  
    // 错误:构造方法不能有返回值类型  
    public void Cat() {  
        System.out.println("构造方法");  
    }  
}

正确写法

class Cat {  
    // 正确:构造方法没有返回值类型  
    public Cat() {  
        System.out.println("构造方法");  
    }  
}

原因分析:构造方法的格式要求严格,不能有返回值类型,连 void 都不能写。

⚠️ 坑点 2:忘记手动添加无参构造

错误写法

class Cat {  
    // 只写了有参构造,没有无参构造  
    public Cat(String name) {  
        this.name = name;  
    }  
    
    String name;  
}
// 错误:没有无参构造,无法这样创建对象
Cat cat = new Cat();

正确写法

class Cat {  
    // 手动添加无参构造  
    public Cat() {  
    }  
    
    // 有参构造  
    public Cat(String name) {  
        this.name = name;  
    }  
    
    String name;  
}
// 正确:现在可以用无参构造创建对象
Cat cat = new Cat();

原因分析:一旦手动写了构造方法,Java 就不再自动生成默认无参构造,需要手动添加。

⚠️ 坑点 3:在 static 方法中使用 this

错误写法

class Cat {  
    String name;  
    
    // 错误:static 方法中不能使用 this  
    public static void staticMethod() {  
        System.out.println(this.name);  
    }  
}

正确写法

class Cat {  
    static String name;  
    
    // 正确:static 方法使用 static 变量  
    public static void staticMethod() {  
        System.out.println(name);  
    }  
}

原因分析static 方法属于类,不属于对象,没有「当前对象」,所以不能使用 this