当前位置: 首页 > news >正文

Java 对象和类

一、核心概念:类与对象

1.1 什么是类 (Class)?

是创建对象的模板蓝图。它定义了一组具有相同属性(字段)和行为(方法)的对象的共同特征。

  • 抽象性:类是抽象的概念,内存中不直接存储类的实例数据(除非是静态变量)。
  • 定义:使用class关键字。

1.2 什么是对象 (Object)?

对象是类的实例(Instance)。它是根据类模板创建出来的具体实体,存在于内存中,拥有具体的属性值。

  • 具体性:对象是实实在在的,占用内存空间。
  • 创建:使用new关键字。

比喻

  • = 建筑图纸(定义了房子有几间房、什么结构)。
  • 对象= 根据图纸盖出来的具体房子(张三的房子、李四的房子,每栋房子的具体装修不同)。

二、类的定义与结构

2.1 基本语法

publicclass类名{// 1. 成员变量 (属性/字段) - 描述对象的状态privateStringname;privateintage;// 2. 构造方法 (Constructor) - 用于初始化对象public类名(Stringname,intage){this.name=name;this.age=age;}// 3. 成员方法 (行为) - 描述对象能做什么publicvoidsayHello(){System.out.println("你好,我是"+name);}// Getter 和 Setter 方法 (封装)publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}}

2.2 成员变量 vs 局部变量

特性成员变量 (Member Variables)局部变量 (Local Variables)
位置类中,方法外方法内、代码块内、参数列表
生命周期随对象创建而存在,随对象销毁而消失随方法调用而存在,方法结束即消失
默认值(int=0, boolean=false, 引用=null)(使用前必须手动赋值)
作用域整个类定义它的方法或代码块
存储位置堆内存 (对象的一部分)栈内存

三、对象的创建与使用

3.1 创建对象的步骤

  1. 加载类:JVM 加载.class文件。
  2. 分配内存:在堆内存中为对象分配空间。
  3. 初始化:执行构造方法,给成员变量赋值。
  4. 返回引用:将对象的内存地址返回给引用变量。

3.2 代码示例

publicclassStudent{Stringname;intage;// 构造方法publicStudent(Stringname,intage){this.name=name;this.age=age;}publicvoidstudy(){System.out.println(name+"正在学习Java");}}publicclassMain{publicstaticvoidmain(String[]args){// 1. 声明引用变量 (栈内存)Students1;// 2. 创建对象 (堆内存)s1=newStudent("张三",20);// 3. 使用对象System.out.println("姓名:"+s1.name);// 访问属性s1.study();// 调用方法// 创建第二个对象Students2=newStudent("李四",22);s2.study();}}

四、构造方法 (Constructor)

4.1 特点

  • 方法名必须与类名完全相同
  • 没有返回值类型(连void都不能写)。
  • new对象时自动调用。
  • 用于初始化对象的状态。

4.2 构造方法的重载

一个类可以有多个构造方法,只要参数列表不同(类型、个数、顺序)。

publicclassPerson{Stringname;intage;// 无参构造方法publicPerson(){System.out.println("无参构造被调用");}// 全参构造方法publicPerson(Stringname,intage){this.name=name;this.age=age;}// 单参构造方法publicPerson(Stringname){this.name=name;this.age=18;// 默认年龄}}

4.3 默认构造方法

  • 如果类中没有定义任何构造方法,Java 编译器会自动提供一个无参构造方法
  • 一旦定义了任意构造方法,编译器不再提供默认无参构造方法。

五、关键字详解

5.1this关键字

  • 含义:代表当前对象的引用(即调用该方法或访问该属性的对象本身)。
  • 常见用法
    1. 区分成员变量和局部变量(当参数名与成员变量名相同时)。
    2. 在构造方法中调用其他构造方法(this(...)必须是第一行)。
    3. 作为方法的返回值,返回当前对象。
publicclassStudent{privateStringname;privateintage;publicStudent(Stringname,intage){this.name=name;// this.name 指成员变量,name 指参数this.age=age;}publicvoidintroduce(){System.out.println("我是"+this.name);}}

5.2new关键字

  • 用于在堆内存中创建对象实例。
  • 返回对象的内存地址(引用)。

六、内存分析 (JVM 内存模型)

理解对象和类,必须理解内存分布:

  1. 栈内存 (Stack)

    • 存储局部变量(包括引用变量,如Student s1)。
    • 存储方法调用的帧(参数、局部变量)。
    • 线程私有,生命周期短。
  2. 堆内存 (Heap)

    • 存储对象实例new Student(...)创建的部分)。
    • 存储数组。
    • 所有线程共享,由垃圾回收器 (GC) 管理。
  3. 方法区 (Method Area / Metaspace)

    • 存储类信息(类名、字段、方法、常量)。
    • 存储static修饰的变量。
    • 所有线程共享。

对象创建过程图解

main 方法 (栈) 堆内存 (Heap) 方法区 (Method Area) +-------------+ +-------------+ +------------------+ | Student s1 | ----> | [对象地址] | | Class: Student | | (引用变量) | | name: "张三"| | - name (String) | +-------------+ | age: 20 | | - age (int) | | | | + study() | +-------------+ +------------------+

七、封装 (Encapsulation)

7.1 概念

将对象的属性隐藏起来(private),只通过公共方法(publicgetter/setter)来访问和修改。

7.2 好处

  • 安全性:防止外部随意修改内部数据(如年龄不能为负数)。
  • 灵活性:内部实现改变不影响外部调用。
  • 可维护性:便于统一管理和调试。

7.3 代码示例

publicclassAccount{privateStringaccountNo;privatedoublebalance;// 余额,外部不能直接修改publicAccount(StringaccountNo,doublebalance){this.accountNo=accountNo;setBalance(balance);// 通过方法设置,进行校验}// GetterpublicdoublegetBalance(){returnbalance;}// Setter (包含逻辑校验)publicvoidsetBalance(doublebalance){if(balance>=0){this.balance=balance;}else{System.out.println("余额不能为负数!");}}// 存款方法publicvoiddeposit(doubleamount){if(amount>0){this.balance+=amount;}}}

八、对象作为参数和返回值

8.1 对象作为参数

Java 中对象传递是值传递,传递的是引用的副本

  • 在方法内修改对象的属性,会影响原对象。
  • 在方法内让引用指向新对象,不会影响原引用。
publicclassTest{publicstaticvoidmodify(Students){s.age=25;// 修改属性,原对象改变s=newStudent("王五",30);// 改变引用指向,原引用不变}publicstaticvoidmain(String[]args){Students1=newStudent("赵六",20);modify(s1);System.out.println(s1.age);// 输出 25 (属性被改了)System.out.println(s1.name);// 输出 "赵六" (引用没变)}}

8.2 对象作为返回值

publicStudentcreateStudent(){returnnewStudent("测试",18);}

九、常见面试题与易错点

  1. ==equals()的区别?

    • ==:比较基本数据类型时比较;比较引用类型时比较内存地址
    • equals():默认比较地址(同==),但通常被重写(如 String, Integer)来比较内容
  2. 为什么要有构造方法?

    • 确保对象在创建时就被正确初始化,避免使用未初始化的对象。
  3. 静态变量 (static) 与对象的关系?

    • 静态变量属于,所有对象共享同一份静态变量。
    • 成员变量属于对象,每个对象都有自己的一份。
  4. 匿名对象的使用场景?

    • 只调用一次方法时:new Student().study();
    • 作为参数传递时:method(new Student());

十、综合实战案例

场景:模拟一个简单的银行账户管理系统。

// 1. 定义类classBankAccount{// 属性privateStringaccountNumber;privateStringownerName;privatedoublebalance;// 构造方法publicBankAccount(StringaccountNumber,StringownerName,doubleinitialBalance){this.accountNumber=accountNumber;this.ownerName=ownerName;if(initialBalance>=0){this.balance=initialBalance;}else{this.balance=0;}}// 存款publicvoiddeposit(doubleamount){if(amount>0){balance+=amount;System.out.println("存款成功,当前余额:"+balance);}}// 取款publicvoidwithdraw(doubleamount){if(amount>0&&amount<=balance){balance-=amount;System.out.println("取款成功,当前余额:"+balance);}else{System.out.println("取款失败:余额不足或金额非法");}}// 查询余额publicdoublegetBalance(){returnbalance;}// 显示信息publicvoidshowInfo(){System.out.println("账号:"+accountNumber+", 户名:"+ownerName+", 余额:"+balance);}}// 2. 测试类publicclassBankSystem{publicstaticvoidmain(String[]args){// 创建对象BankAccountacc1=newBankAccount("6222001","张三",1000.0);BankAccountacc2=newBankAccount("6222002","李四",500.0);// 操作对象acc1.showInfo();acc1.deposit(500);acc1.withdraw(200);System.out.println("---");acc2.showInfo();acc2.withdraw(600);// 余额不足// 比较对象System.out.println("acc1 和 acc2 是同一个对象吗? "+(acc1==acc2));// false}}

总结

  • 是模板,对象是实例。
  • 构造方法负责初始化。
  • 封装保护数据安全。
  • 内存模型:栈存引用,堆存对象,方法区存类信息。
  • 掌握对象和类是学习 Java 面向对象编程(OOP)的基石,后续继承、多态都基于此。
http://www.jsqmd.com/news/584336/

相关文章:

  • 一站式图像生成与编辑:Nano Banana 图像生成与编辑 API(包含多个示例和实用技巧)
  • 避坑指南:当你的回归系数突然变号或不显著时,可能是多重共线性在捣鬼
  • Unity自定义鼠标指针样式与交互效果实战
  • OpenClaw+千问3.5-27B创作助手:从大纲到公众号图文全自动生成
  • 复现24年子刊:通过模式匹配筛选指定能带
  • 用Python和NumPy手把手教你理解导数:从瞬时速度到反向传播的数学基础
  • SpringBoot整合阿里云短信服务实战:从零到一构建企业级消息推送
  • 基于SpringBoot+Vue的新闻推荐系统管理系统设计与实现【Java+MySQL+MyBatis完整源码】
  • Logisim实战:从零构建学号音乐盒的数字系统设计
  • 手把手教你用PyTorch和DDPG搞定MountainCarContinuous-v0(附200轮收敛代码)
  • 别再只盯着航拍了!聊聊无人机装上‘手’之后,在巡检和救援中的那些硬核应用
  • 出口韩国!广舟包装为汽车行业提供优质吸塑托盘解决方案
  • Flutter权限请求别再踩坑了!手把手教你用permission_handler搞定iOS 17和Android 14适配
  • 避坑指南:Oracle EBS AR模块数据查询中的10个常见错误与优化技巧
  • OpenClaw+OCR增强:Kimi-VL-A3B-Thinking复杂图文混合识别方案
  • OpenClaw批量处理技巧:千问3.5-35B-A3B-FP8高效完成百份文档转换
  • YOLOv8-OBB C++工程部署实战:从模型转换到多场景推理
  • Arduino数字电位器库MCP_POT:SPI驱动MCP41/42系列详解
  • 从健康码崩溃到秒杀系统:QPS、TPS、RT这些指标到底怎么用?
  • Elasticsearch内存管理全攻略:从circuit_breaking_exception到性能优化的完整配置指南
  • OpenClaw性能调优:Qwen3-14B并发请求处理最佳实践
  • 实测:千元安卓机离线跑DeepSeek-R1 1.5B模型,写代码、解数学题够用吗?
  • OpenClaw+千问3.5-35B-A3B-FP8:自动化学习笔记整理系统
  • OpenClaw备份恢复:迁移Phi-3-vision-128k-instruct配置到新设备的正确姿势
  • 别再只会点灯了!用STM32CubeIDE的HAL库玩转PWM,从呼吸灯到电机调速的保姆级实战
  • ArcGIS与Python高效结合:Arcpy实战技巧解析
  • 搞不定CAN总线匹配电阻?实测告诉你120Ω电阻怎么加、阻值怎么测、位置怎么放才不出错
  • 树莓派远程开发环境搭建:从Raspberry Pi OS烧录到VNC文件传输的完整避坑指南
  • 从理论到流水线:TLB与Cache协同设计的实战解析
  • 如何利用高端SEO提升网站的品牌影响力