我学习到的Java类和对象区别

基础概念

  • 类是创建对象的模板或蓝图 。对象是现实世界中的实体类的实例
  • 声明类使用 Java 关键字 *class,Java 中的所有关键字都是小写字母。
  • class 关键字后面跟着类名,根据 Java 的约定,首字母必须大写。
  • *new* 关键字会在运行时动态地在 RAM(随机存取存储器)中创建对象,并返回所创建对象的引用(地址)。该引用存储在 obj 中,将来将使用该引用来访问对象。

一、Class 类的 5 个特性

  1. 类是相似对象的集合模板

类定义了一批事物共同的属性(字段)和行为(方法),比如User类,规定了所有用户都要有id、username属性、login()方法,是对同类事物的抽象归纳。

  1. 类是概念性的模板

就像房屋设计图纸,图纸只是设计方案,不是真实能住的房子;它只规定房子的结构,本身不能直接使用。

  1. 类不会分配堆内存

编译阶段加载类信息会占用少量方法区内存,但不会在堆上分配实例内存;只有用new创建对象时,才会给对象分配堆内存。

  1. 类可以不依赖任何对象独立存在

你可以只写好User.java编译出User.class,全程不创建任何User对象,这个类依然能被 JVM 识别、加载。

  1. 类的字段没有绑定具体数值

User类里只会声明private String username;,不会写死username = "张三";它只定义 "有这个属性",不设置具体内容。

二、Object 对象的 5 个特性

  1. 对象是类的实例

按照User这个图纸盖出来的某一套真实房子 ,就是对象;代码里User zhangsan = new User();zhangsan就是User类的实例对象。

  1. 对象是真实存在的实体

它是能实际调用方法、存储数据的实体,就像建好的房子可以入住、使用。

  1. 每个对象都有独立的内存空间

User u1 = new User(); User u2 = new User();u1u2在堆上是两块独立内存,修改u1的属性不会影响u2

  1. 对象不能脱离类存在

Java 里所有对象都必须由对应的类(或父类)来定义结构,没有无模板凭空出现的对象;创建对象时 JVM 必须先加载它所属的类。

  1. 每个对象的字段都有专属具体数值

zhangsan.username = "张三"; lisi.username = "李四";,两个对象的同一个字段可以存完全不同的数据,互相隔离。

三、类和对象对比总结

  1. 关系:先有类,才能造对象,类是图纸,对象是成品;
  2. 内存:类加载放方法区,对象创建在堆区;
  3. 数据:类只定义字段名,对象才存字段的实际内容;
  4. 独立性:类可以零实例存在,对象必须依附类存在。

四、方法区存类、堆存对象

  • 方法区(Method Area)

专门存所有 Class 模板本身 :代码里写的类名、属性定义、方法代码、常量、注解全部存在这里。程序启动后 JVM 会把.class字节码解析好,放进方法区,全程只加载 1 次,所有对象共用这一份模板。

  • 堆(Heap)

专门存new出来的实例对象(真实房子) ,每一次new都会在堆里开辟一块独立空间,存这个对象专属的字段值。

写一段极简 Java 代码,逐行看内存分配

typescript 复制代码
// 1. 定义User类(图纸)
public class User {
    // 模板里只声明有name、age,没有具体值
    String name;
    Integer age;

    // 模板里的方法代码,只存一份
    public void sayHi() {
        System.out.println("你好");
    }
}

// 主程序
public class Test {
    public static void main(String[] args) {
        // 2. 第一次new,堆里造第一个房子
        User zhangsan = new User();
        zhangsan.name = "张三";
        zhangsan.age = 20;

        // 3. 第二次new,堆里再造一间独立房子
        User lisi = new User();
        lisi.name = "李四";
        lisi.age = 22;
    }
}

1)程序启动时:方法区发生什么?

JVM 读取User.class字节码,把下面这些模板信息一次性存入方法区,永久只存一份:

  • 类名:User
  • 字段定义:String name、Integer age(只是声明有这两个属性,没有张三 / 李四的值)
  • 方法完整代码:sayHi () 的执行逻辑
  • 构造函数代码

类比前端:方法区 ≈ 你项目里class User {}这段 TS 源码定义,整个项目全局只有这一份类型模板,不会复制多份。

2)执行 new User () 时:堆区发生什么?

每执行一次new User(),JVM 在堆内存新开一块独立空间

  1. zhangsan = new User()堆中一块内存:name = "张三",age = 20
  2. lisi = new User()堆中另一块完全隔离的内存:name = "李四",age = 22

两块堆内存互不干扰,修改zhangsan.age,不会影响lisi

五、方法区和堆区核心区分

1. 存储内容完全不同

  • 方法区:存模板定义(有什么属性、有什么方法,没有具体数据)
  • 堆区:存实例数据(张三、李四这种真实业务值,每个对象独立一份)

2. 创建时机不一样

  • 方法区:程序启动,第一次用到这个类时自动加载,只加载 1 次
  • 堆区:只有写new的时候才分配内存,写几次 new 就开辟几块内存

3. 数量关系

  • 方法区:一个类永远只占 1 份空间
  • 堆区:一个类可以对应 N 个堆对象,N 由你new的次数决定

疑问:如果我只写 class,不 new 任何对象,内存怎么分配?

方法区依然会存入这个类的模板;但堆里是空的,没有分配任何内存。对应业务:你定义了实体类,但全程没有查询数据库、没有创建实例,堆不会占用额外空间。

相关推荐
前端工作日常15 小时前
我学习到的Java类完整结构
java·后端
什巳16 小时前
JAVA练习309- 二叉树的层序遍历
java·数据结构·算法·leetcode
宠友信息16 小时前
消息序号如何保证即时通讯源码聊天记录稳定加载
java·spring boot·redis·python·mysql·uni-app
圣光SG16 小时前
Java Web入门基础知识笔记
java·前端·笔记
Csvn16 小时前
📊 SQL 入门 Day 6:多表查询 — JOIN 的四种姿势
后端·sql
行思理17 小时前
微信支付“商家转账用户确认模式”,新手教程
java·开发语言·微信
空中湖17 小时前
Spring AI RAG 完整实战:从零搭建企业知识库问答系统
java·人工智能·spring
Ai拆代码的曹操18 小时前
K8s Pod Pending 逐层排查:从 FailedScheduling 到 PVC StorageClass 不存在的实战记录
java·linux·kubernetes
hold?fish:palm18 小时前
RDB全量快照备份
c++·redis·后端