一、面向对象核心概念

1.1 基本思想

将程序拆解为对象的集合,每个对象是"数据(属性)+ 行为(方法)"的封装体。程序运行的本质是对象之间互相发送消息(方法调用)。

1.2 三大特性

特性 说明 类比
封装 隐藏内部实现细节,仅暴露必要接口 手机充电口对外,内部电路隐藏
继承 子类复用父类的属性和方法,减少重复代码 大学生类继承学生类
多态 同一方法,不同对象表现不同行为 动物类 叫():猫→"喵"、狗→"汪"

二、类与对象

2.1 概念对应

概念 Java 表述
类属性 static 修饰的成员变量(静态变量)
实例属性 无 static 的成员变量
实例方法 无 static 的成员方法(隐含 this
类方法 static 修饰的方法
初始化方法 构造方法(与类同名,无返回值)

2.2 完整代码示例:学生类

public class Student {
    // 1. 类属性(静态变量):所有对象共享
    public static String species = "人类";
    public static String school = "XX中学";

    // 2. 实例属性(成员变量):每个对象独有
    private String stuId;
    private String name;
    private int age;
    private String grade;  // 默认值 null

    // 3. 构造方法:创建对象时初始化
    public Student(String stuId, String name, int age) {
        this.stuId = stuId;
        this.name = name;
        this.age = age;
    }

    // 4. 实例方法:操作实例属性
    public void attendClass(String course) {
        System.out.printf("%s(学号%s)正在上%s课%n", this.name, this.stuId, course);
    }

    // 5. 类方法(静态方法):操作类属性
    public static void showSchool() {
        System.out.println("当前学校:" + Student.school);
    }

    // 6. 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) { this.age = age; }
    public String getGrade() { return grade; }
    public void setGrade(String grade) { this.grade = grade; }

    // 测试入口
    public static void main(String[] args) {
        Student stu1 = new Student("2026001", "张三", 16);
        stu1.setGrade("高一1班");
        stu1.attendClass("数学");  // 张三(学号2026001)正在上数学课

        Student stu2 = new Student("2026002", "李四", 17);
        stu2.setGrade("高一2班");
        stu2.attendClass("英语");  // 李四(学号2026002)正在上英语课

        System.out.println(Student.species);  // 人类
        Student.showSchool();  // 当前学校:XX中学
    }
}

2.3 static 与非 static

修饰符 级别 所属 访问方式
static 类级别 整个类,所有对象共享 类名 / 对象名(推荐类名)
无 static 对象级别 每个对象独有 必须通过对象访问

三、封装

3.1 核心定义

封装是面向对象三大特性之一,核心原则:隐藏内部细节,暴露安全接口。通过访问控制禁止外部直接操作内部数据,仅通过指定方法交互。

3.2 实现步骤

步骤一:私有化成员变量

public class Student {
    private String name;
    private int age;
}

步骤二:提供公共 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 <= 120) {
        this.age = age;
    } else {
        throw new IllegalArgumentException("年龄必须在0-120之间");
    }
}

步骤三:有参构造复用 setter

public Student(String name, int age) {
    this.name = name;
    this.setAge(age);  // 复用校验逻辑
}

3.3 访问权限修饰符

修饰符 本类 同包类 子类(不同包) 其他类
private 可访问 不可 不可 不可
默认(不写) 可访问 可访问 不可 不可
protected 可访问 可访问 可访问 不可
public 可访问 可访问 可访问 可访问

封装中:成员变量用 private,getter/setter 用 public

3.4 注意事项

  1. getter/setter 命名规范:get + 变量名首字母大写(布尔类型可用 is),set + 变量名首字母大写。
  2. 构造方法中调用 setter 以复用数据校验逻辑。
  3. 不过度封装:仅暴露必要的接口,不需要每个成员都提供 getter/setter。

四、Java 内存分区与对象内存分析

4.1 内存分区

内存区域 存储内容 生命周期
栈内存 局部变量、方法调用栈 方法执行完毕出栈释放
堆内存 new 创建的对象(含成员变量)、JDK 7+ 字符串常量池 GC 自动回收

4.2 单个对象调用方法 — 内存流程

Person p = new Person();
p.name = "张三";
p.age = 20;
p.show();
  1. main 进栈,定义 p
  2. new Person():堆中开辟空间,name=nullage=0,生成地址(如 0x123)。
  3. p(栈)存储地址 0x123,指向堆中对象。
  4. p.name = "张三":通过地址修改堆中 name;同理 age = 20
  5. p.show()show 进栈,this 指向 0x123,读取 name 和 age 输出。
  6. show 出栈 → main 出栈。

4.3 多个对象调用方法

Person p1 = new Person();
p1.name = "王五";

Person p2 = new Person();
p2.name = "赵六";

p1.show();
p2.show();
  • p1 指向堆空间 1(0x789),p2 指向堆空间 2(0xabc)。
  • 两次 show() 调用时,this 分别指向各自堆对象,输出各自数据。

4.4 多个引用指向同一对象

Person p3 = p1;  // p3 和 p1 指向堆中同一对象

修改 p3 的成员变量会影响 p1,因为指向同一堆地址。

五、基本数据类型与引用数据类型

5.1 基本数据类型(8 种)

类型 关键字 占用内存 取值范围 默认值
字节型 byte 1 字节 -128 ~ 127 0
短整型 short 2 字节 -32768 ~ 32767 0
整型 int 4 字节 约 ±21 亿 0
长整型 long 8 字节 -2^63 ~ 2^63-1 0L
单精度浮点 float 4 字节 约 ±3.4×10^38 0.0f
双精度浮点 double 8 字节 约 ±1.8×10^308 0.0d
字符型 char 2 字节 \u0000 ~ \uffff '\u0000'
布尔型 boolean 1 字节 true / false false
  • 直接存储值,存于栈内存(局部变量)。
  • 赋值时为值传递:int b = a; 复制的是值,修改 b 不影响 a

5.2 引用数据类型

包含类(String、自定义类)、接口(List)、数组(int[])。变量存储的是堆对象地址。赋值时为引用传递:复制的是地址,指向同一堆对象。

5.3 值传递 vs 引用传递

// 基本类型:值传递,不影响原变量
public static void change(int num) { num = 20; }
int a = 10; change(a);
System.out.println(a);  // 10

// 引用类型:引用传递,修改堆对象
public static void change(Person p) { p.name = "李四"; }
Person p1 = new Person(); p1.name = "张三"; change(p1);
System.out.println(p1.name);  // 李四

5.4 String 的特殊性

String 是引用类型但不可变,赋值 / 传参时表现类似值传递:

public static void change(String str) { str = "world"; }  // str 指向新对象
String s = "hello"; change(s);
System.out.println(s);  // hello(原对象未变)

5.5 总结对比

对比项 基本数据类型 引用数据类型
存储内容 实际值 堆对象地址
存储位置 栈(引用)+ 堆(对象)
传递方式 值传递(副本) 引用传递(地址)
修改影响 不影响原变量 影响堆中对象(String 除外)

六、this 关键字

6.1 核心作用

this 代表当前对象的引用(堆内存地址),由 JVM 自动传入每个非静态方法。

作用 说明
区分成员变量与局部变量 this.name = name;
调用当前对象的成员方法 this.show();
调用当前类的构造方法 this(参数),必须位于构造方法第一行
作为方法返回值 return this;

6.2 内存原理

public void setName(String name) {
    this.name = name;  // this 指向调用该方法的对象
}

Student s1 = new Student();  // 假设地址 0x123
s1.setName("张三");  // JVM 实际传递:setName(s1, "张三"),this = 0x123

方法进栈时 JVM 自动传入调用对象的地址作为 this,通过 this 定位堆中对象并操作其成员。

6.3 注意事项

  1. 仅非静态方法中有 this,静态方法属于类,不依赖对象。
  2. this 不能为 null,对象创建后地址非 null
  3. this(参数) 调用构造方法时,必须写在构造方法的第一行。

七、成员变量与局部变量

7.1 定义

类型 定义位置 所属
成员变量 类中、方法外 对象 / 类
局部变量 方法内、代码块中、方法参数 方法 / 代码块

7.2 五维度对比

对比维度 成员变量 局部变量
定义位置 类中、方法外 方法内 / 代码块 / 方法参数
作用域 整个类(随修饰符变化) 所在的方法 / 代码块内部
默认值 有默认值 无默认值,须显式赋值后使用
存储位置 实例:堆内存;静态:方法区 栈内存(方法栈帧中)
生命周期 实例:随对象创建 / 回收;静态:随类加载 / 卸载 随方法 / 代码块执行创建、结束销毁

7.3 同名变量优先级

方法内默认访问局部变量;访问成员变量需使用 this(实例成员)或类名(静态成员):

class Person {
    String name = "成员变量";

    public void test() {
        String name = "局部变量";
        System.out.println(name);       // 局部变量
        System.out.println(this.name);  // 成员变量
    }
}

八、总结

  1. 类是抽象模板,对象是具体实例,通过 new 类名(参数) 创建。
  2. static 区分类级别和对象级别的属性和方法;属性私有化 + getter/setter 实现封装。
  3. 对象存堆、引用存栈;多引用可指向同一对象。
  4. 基本类型值传递、引用类型地址传递(String 不可变特性例外)。
  5. this 由 JVM 自动传入,关联方法与调用对象,实现对当前对象成员的操作。
  6. 成员变量作用域广、有默认值;局部变量作用域窄、须显式赋值。

更多推荐