【六. Java面向对象编程入门指南】

6. java面向对象基础

6.1 设计对象并使用

6.1.1 类与对象的本质理解

  • 类的本质:类是对现实事物的模板化抽象。好比 “图纸”

  • 对象的本质:对象是类的具体实例。好比根据图纸造出的 “真实汽车”

6.1.2 类的定义细节

  • 成员变量的默认值规则

    数据类型默认值示例(未赋值时)
    整数类型(如 int)0int age; → 0
    浮点类型(如 double)0.0double price; → 0.0
    字符类型(char)‘\u0000’(空字符)char gender; → 空字符
    布尔类型(boolean)falseboolean isStudent; → false
    引用类型(如 String)nullString name; → null
  • 成员方法的注意事项:

    • 无需static修饰:因为成员方法属于对象层面的行为,依赖具体对象调用

    • 可直接访问成员变量:成员方法内部可直接使用成员变量名,无需 “对象名.” 前缀(本质是通过this隐式调用)

6.1.3 对象的创建与使用深度解析

  • 创建对象的底层逻辑:

    • 分配堆内存:new 类名()会在堆内存中开辟一块空间,存储对象的属性值和方法引用

    • 初始化属性:成员变量按默认值初始化(如int为 0,Stringnull

    • 返回对象地址:将堆内存地址赋值给栈中的引用变量(如Phone p = ...中的p

  • 访问成员的底层逻辑

    • 访问属性:对象名.属性名 → 通过引用变量找到堆内存中的对象,直接操作属性值例子: p.brand = "小米" → 找到p指向的对象,修改其brand属性为 “小米”

    • 调用方法:对象名.方法名() → 通过引用变量找到对象,根据方法引用找到方法区中的代码执行例子:p.call() → 执行方法区中Phone类call()方法逻辑

  • 例子:

      public class Car {  
          // 成员变量(属性)  
          String color;   // 颜色,默认null  
          int speed;      // 速度,默认0  
          boolean isStart; // 是否启动,默认false  
      
          // 成员方法(行为)  
          public void start() { // 启动车  
              isStart = true;  
              System.out.println("汽车已启动,当前速度:" + speed);  
          }  
      
          public void accelerate(int addSpeed) { // 加速  
              if (!isStart) { // 未启动时无法加速  
                  System.out.println("请先启动汽车!");  
                  return;  
              }  
              speed += addSpeed;  
              System.out.println("加速后速度:" + speed + "km/h");  
          }  
      }  
      
      // 使用对象  
      public class CarDemo {  
          public static void main(String[] args) {  
              // 1. 创建对象  
              Car c = new Car();  
      
              // 2. 访问属性(直接操作,未封装时)  
              System.out.println("初始颜色:" + c.color); // 输出:null  
              c.color = "红色"; // 赋值  
              System.out.println("修改后颜色:" + c.color); // 输出:红色  
      
              // 3. 调用方法  
              c.start(); // 输出:汽车已启动,当前速度:0  
              c.accelerate(50); // 输出:加速后速度:50km/h  
              c.accelerate(-20); // 合法,速度减为30km/h  
          }  
      }  

6.2 封装

6.2.1 为什么需要封装?

  • 场景举例:若直接暴露成员变量(如public int age;),外部代码可能赋值非法数据(如年龄 - 5 岁),导致逻辑错误

  • 封装的优势:

    • 数据安全:通过setter方法添加校验逻辑,防止非法数据

    • 结构清晰:外部只需通过固定方法操作数据,无需关心内部实现

    • 可维护性:修改内部逻辑时(如调整年龄范围),只需修改setter,不影响外部调用

6.2.2 private关键字的深度用法

私有化成员变量的步骤:

  1. 声明时加private

    private String name; // 私有化姓名,外部不可直接访问

  2. 提供publicgetter/setter方法:

  * `getter`方法:用于读取属性值,命名规则`getXxx()`(布尔类型用`isXxx()`)
    
        public String getName() { // 获取姓名  
            return name;  
        }  
  • setter方法:用于设置属性值,可添加校验逻辑,命名规则setXxx(参数)
        public void setAge(int age) { // 设置年龄  
            if (age < 0 || age > 150) { // 年龄必须在0-150之间  
                System.out.println("年龄非法!请重新设置。");  
                return; // 终止方法,不赋值  
            }  
            this.age = age; // 合法时赋值  
        }  

封装 vs 不封装的对比:

场景未封装(public 成员变量)封装(private+getter/setter)
赋值年龄 - 5 岁直接赋值成功,逻辑错误setAge(-5)触发校验,拒绝赋值
代码维护(修改年龄范围)需修改所有赋值代码只需修改setAge方法的校验逻辑
外部调用复杂度直接操作属性,耦合度高通过固定方法操作,结构清晰

6.2.3 封装的最佳实践

  • 所有成员变量必须私有化:除非有特殊需求(如工具类的静态变量),否则绝不使用public修饰成员变量

  • setter方法必填校验逻辑:根据业务规则对输入数据进行合法性检查(如年龄、邮箱格式、密码长度等)

  • getter方法保持简单:通常仅返回属性值,不添加复杂逻辑(复杂逻辑应封装到其他业务方法中)

6.3 this关键字

6.3.1 this的三大作用

  1. 区分同名变量:当方法参数与成员变量同名时,用this明确指代成员变量
      public void setName(String name) {  
          this.name = name; // this.name是成员变量,name是方法参数  
      }  
  1. 调用成员方法:在成员方法内部,可通过this.方法名()调用本类的其他成员方法(通常可省略this.
      public void study() {  
          System.out.println("开始学习...");  
          this.doHomework(); // 调用本类的doHomework方法  
      }  
      public void doHomework() {  
          System.out.println("正在写作业...");  
      }  
  1. 调用构造方法:在构造方法中,用this(参数)调用本类的其他构造方法(必须位于构造方法第一行)
      public class Student {  
          private String name;  
          private int age;  
      
          // 无参构造调用有参构造(初始化默认值)  
          public Student() {  
              this("匿名学生", 0); // 调用Student(String, int)构造  
          }  
      
          // 有参构造  
          public Student(String name, int age) {  
              this.name = name;  
              this.age = age;  
          }  
      }  

6.3.2 this的本质:当前对象的引用

  • 当对象stu调用方法setName("张三")时,方法内部的this就代表stu对象

  • 栈内存:stu --> 堆地址0x123  
    
    堆内存(对象):  
    Student {  
        name: null,  
        age: 0,  
        setName(String name) {  
            this.name = name; // this指向stu对象,即给stu的name赋值  
        }  
    }  
    

6.4 构造方法

6.4.1 构造方法的核心特性

  1. 名称必须与类名完全一致(包括大小写):
      public class Dog {  
          public Dog() { // 构造方法名必须是Dog  
          }  
      }  
  1. 没有返回值类型(连void也不能写):
      public Dog() { // 正确  
      }  
      public void Dog() { // 错误!这是普通方法,不是构造方法  
      }  
  1. 创建对象时必须调用:每次使用new关键字创建对象时,必然会执行一个构造方法(默认无参或自定义构造)

6.4.2 默认构造方法与自定义构造的关系

  • 默认构造的生成条件:当类中没有任何构造方法时,系统自动生成无参构造(public 类名() {})。

  • 自定义构造的影响:一旦定义了任意构造方法(无参或有参),系统不再生成默认无参构造

      public class Cat {  
          // 自定义有参构造  
          public Cat(String name) {  
          }  
          // 此时系统不会生成无参构造,以下代码会报错!  
          // Cat c = new Cat(); // 错误:无法找到无参构造  
      }  
  • 推荐做法:无论是否需要,都手动添加无参构造,避免后续扩展时因缺少构造方法报错

6.4.3 构造方法的重载规则

  • 重载条件:构造方法名相同,参数列表不同(参数个数、类型、顺序不同),与返回值无关(构造无返回值)
      public class Person {  
          public Person() {} // 无参构造  
          public Person(String name) {} // 1个参数(String)  
          public Person(int age) {} // 1个参数(int),与上一个构成重载(类型不同)  
          public Person(String name, int age) {} // 2个参数  
      }  
  • 禁止重载的情况:参数列表完全相同,即使方法体不同,也无法构成重载(编译报错)

6.5 标准JavaBean

6.5.1 JavaBean 的完整规范

  1. 成员变量:全部private修饰,禁止外部直接访问
      private String name;  
      private int age;  
  1. 构造方法:提供无参构造和全参构造
      public Student() { //无参构造
      
      }  
      public Student(String name, int age) {  // 全参构造 
          this.name = name;  
          this.age = age;  
      }  
  1. getter/setter方法:为每个成员变量提供对应方法
      public String getName() { 
          return name; 
      }  
      public void setName(String name) {
          this.name = name;
      }  
  1. 可选:实现Serializable接口(用于对象序列化,如网络传输、持久化存储)

6.5.2 快速生成 JavaBean 的技巧(IDE 工具)

  • IDEA 操作:

    • 在类中按Alt+Insert

    • 选择Constructor/Getter and Setter

    • 勾选需要的成员变量

    • 生成代码

6.6 对象内存图

6.6.1 单个对象的内存分布(以Student类为例)

栈内存:s --> 堆地址0x100  
堆内存:  
Student {  
    name: "李四",  // 通过setName赋值  
    age: 20,       // 通过setAge赋值  
    show(): 方法引用 --> 方法区中的show()代码  
}  
方法区:  
Student类的成员方法(show()等)存储在此  

6.6.2 多个对象的内存关系

栈内存:s1 --> 0x100,s2 --> 0x200  
堆内存:  
0x100: Student { name: "A", age: 18 }  
0x200: Student { name: "B", age: 20 }  
方法区:  
Student类的成员方法(show()等)被所有对象共享  

6.7 成员变量与局部变量的区别

对比维度成员变量局部变量
定义位置类中方法外方法内或方法参数
内存位置堆内存(属于对象)栈内存(属于方法栈帧)
生命周期随对象创建而存在,随对象销毁而消失随方法调用而存在,随方法结束而消失
默认值有默认值(如int为 0,String为null)无默认值,必须先赋值后使用
作用域整个类范围内可见仅限方法内或代码块内可见
    public class Demo {  
        int memberVar = 10; // 成员变量,默认值10  
    
        public void method() {  
            int localVar = 20; // 局部变量,无默认值,必须赋值  
            System.out.println(memberVar); // 正确,成员变量可在方法内访问  
            // System.out.println(localVar2); 错误,未定义  
        }  
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值