三、面向对象基础(封装、继承,重点实操,贴合智能体场景)

3.1 面向对象核心思想(自身学习重点:理解面向对象优势)

3.1.1 面向对象与面向过程的核心区别(表格对比,清晰直观,便于自身记忆和读者理解)

  • 在开始这次 Java 面向对象的学习之前,先给大家讲一个小故事,帮大家快速 get 核心思路~         博主有一个朋友,他可以说是 “懒到丧失生活自理能力”,不管做什么事,从来不会自己动手,只会找别人帮忙—这就像我们面向对象的核心逻辑:不关注 “步骤”,只关注 “谁能帮我做” 。其中有一件事特别让人印象深刻,就是打水。在座的美丽帅气的读者们,应该都有过这种体验:身边总有那么些人,看到别人要去打水,就会顺口说一句 “帮我也带一杯呗”。我的这个朋友,就是这类人的 “天花板”,在我们班里,只要有人起身要去打水,他绝对是第一个举手的,从来不会自己跑一趟,只会找同学帮忙完成 “打水” 这件事。

            他不用知道 “打水要走哪条路、怎么开水龙头、怎么接水、怎么拿回来”(这就是面向过程,关注步骤),他只需要找到 “会打水的同学”(这就是对象),让这个同学帮他完成 “打水” 这个行为(这就是对象的方法)。

             其实这就是 Java 面向对象的核心:我们不用亲自实现所有步骤,只需要找到对应的 “对象”,调用它的 “行为”,就能完成我们想要的功能 —— 就像我这个朋友,不用自己打水,找对人(对象),就能喝到水~

  • 接下来给大家提供一个表格从更加科学的角度下让大家了解一下面向对象与面向过程的区别:

  • 对比维度 面向过程 (POP) 面向对象 (OOP)
    核心思想 过程 / 步骤为中心,一步一步实现 对象为中心,通过对象调用功能
    关注点 关注怎么做(步骤、流程) 关注谁来做(对象、行为)
    代码特点 方法调用,线性执行 封装类、创建对象、模块化
    复用性 差,代码重复多 高,可继承、可复用、可扩展
    维护性 难,修改一处影响全部 易,低耦合、独立模块
    适合场景 简单逻辑、小功能 复杂项目、大型系统、业务开发
    举例理解 自己一步步做饭(买菜→洗菜→炒菜) 点外卖,让外卖员对象完成做饭
    开发效率

3.1.2 类与对象的定义:语法规范、成员变量、成员方法

  • 类的三要素:

       类:抽象模板,描述一类事物的属性和行为,比如学生类,里面就可以有学生的属性,姓名、年龄、学号、班级等。学生的行为包括学习、打水、打扫卫生等等,这些就是方法。类里包括成员变量和成员方法两种。

       成员变量:属性(姓名、年龄、成绩…)。写在类里方法外,代表全局变量

       成员方法:行为(学习、吃饭、跑步…)。定义的方法使用的时候调用即可

  • 变量分为成员变量(全局变量)、局部变量,定义在方法里面的变量就是局部变量只在这一个类里面起作用,而成员变量可以在整个类中起作用。

3.1.3 对象的创建与初始化:new关键字、构造方法的调用(自身实操创建对象,掌握初始化流程)

       在 Java 中,想要使用一个类,必须通过new 关键字来创建该类的对象,这个过程就是对象的创建。new 关键字的作用是在堆内存中为对象开辟空间,并自动调用构造方法完成对象的初始化(给成员变量赋值)。构造方法是与类名同名、没有返回值类型的特殊方法,专门用于对象创建时初始化。创建对象的完整流程:new 关键字申请内存 → 成员变量赋默认值 → 执行构造方法手动赋值 → 对象创建完成,可以调用属性和方法。

       只有这个类当中有main方法才可以执行调试。而main也是程序的入口,进入后以从上到下的0顺序依次执行。当我们调用一个同包同类下方法的时候,需要看这个方法的类型,有没有返回值,需不需要传入参数等等。

// 定义一个学生类
class Student {
    // 成员变量
    String name;
    int age;
    // 构造方法:与类名同名,无返回值类型
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("构造方法已调用,对象初始化完成");
    }
    // 成员方法
    public void showInfo() {
        System.out.println("姓名:" + name + ",年龄:" + age);
    }
}
// 测试类:创建并使用对象
public class Test {
    public static void main(String[] args) {
        // 1. 使用new关键字创建对象,自动调用构造方法初始化
        Student stu = new Student("小明", 18);
        
        // 2. 调用对象的方法
        stu.showInfo();
    }
}

    • 上图代码中的Student方法后面()中写的就是需要传入的参数个数以及类型,而void代表无返回值。new一个对象的意思给存储你要输入值一个确定的标识,便于后续的调用。也可以说是给你new出来的孩子一个名字,之后只要叫它的名字就可以得到他的属性以及方法。

    3.2 封装详解

    3.2.1 封装的核心原理与优势

    • 首先理解什么是封装,顾名思义哈,封装就是把这个东西封好了,其他人没有办法修改。我们java的封装也是这个目的。类似于全自动洗衣机,洗衣机上面有好多的功能按钮,我们只要点击对应的功能它就可以执行,我们不需要管它内部是怎么工作的。在java当中也是,我们封装好之后,会提供一些固定的接口来供他人使用。

    • 这样的话可以避免其他人随意的修改我们的内容,也降低了学习难度,只要找到具体的功能名字和包就可以使用该功能,不需要明白 内部逻辑是什么样的。

    3.2.2 访问修饰符权限对比

    访问修饰符 同一类内 同一包内 不同包的子类 不同包的非子类 通俗理解 适用场景(详细)
    private(私有的) 我的私人物品,只有我自己能用 1. 修饰成员变量(封装核心,禁止外部直接修改)2. 修饰内部工具方法3. 保证数据安全,只能本类访问
    default(默认 / 包私有)不写关键字 一家人才能用,外人不能用 1. 同包下的工具类、辅助类2. 只给本包内部使用的方法 / 变量3. 不想对外暴露的包级功能
    protected(受保护的) 我和我的家人能用,外人不能用 1. 父子类继承场景2. 希望子类可以访问、重写,但外部不能访问3. 框架、父类模板方法常用
    public(公共的) 公共设施,所有人都能用 1. 对外提供服务的类、接口2. 供外部调用的核心方法3. 项目入口、对外暴露的功能

    3.2.3 封装实操:智能体会话Session实体类

    /**
     * 智能体会话Session实体类
     * 封装会话核心数据,对外提供安全的访问接口
     */
    public class ChatSession {
        // 1. 私有成员变量(封装核心:隐藏内部数据)
        private String sessionId;    // 会话ID(全局唯一)
        private String userId;       // 会话所属用户ID
        private String message;      // 会话消息内容
        private long createTime;     // 会话创建时间戳
    
        // 2. 无参构造方法(创建空会话对象)
        public ChatSession() {
            this.createTime = System.currentTimeMillis(); // 自动生成创建时间
        }
    
        // 3. 全参构造方法(快速初始化完整会话对象)
        public ChatSession(String sessionId, String userId, String message) {
            this.sessionId = sessionId;
            this.userId = userId;
            this.message = message;
            this.createTime = System.currentTimeMillis();
        }
    
        // 4. Getter方法(对外读取数据,无setter保证核心字段不可修改)
        public String getSessionId() {
            return sessionId;
        }
    
        public String getUserId() {
            return userId;
        }
    
        public long getCreateTime() {
            return createTime;
        }
    
        // 5. Setter方法(对外修改数据,可添加业务校验)
        public void setMessage(String message) {
            // 业务校验:消息长度不超过500字符
            if (message != null && message.length() <= 500) {
                this.message = message;
            } else {
                throw new IllegalArgumentException("消息长度超出限制(最多500字符)");
            }
        }
    
        public String getMessage() {
            return message;
        }
    
        // 6. 业务方法:展示会话信息
        public void showSessionInfo() {
            System.out.println("=== 智能体会话信息 ===");
            System.out.println("会话ID:" + sessionId);
            System.out.println("用户ID:" + userId);
            System.out.println("消息内容:" + message);
            System.out.println("创建时间:" + createTime);
        }
    }
    
    // 测试类:验证封装效果
    class ChatSessionTest {
        public static void main(String[] args) {
            // 创建会话对象
            ChatSession session = new ChatSession("S1001", "U2001", "你好,智能体!");
    
            // 合法操作:通过getter读取数据
            System.out.println("会话ID:" + session.getSessionId());
            System.out.println("原消息:" + session.getMessage());
    
            // 合法操作:通过setter修改消息(带校验)
            session.setMessage("我想咨询智能体开发相关问题");
            System.out.println("修改后消息:" + session.getMessage());
    
            // 非法操作:直接访问private变量(编译报错,封装生效)
            // session.sessionId = "S9999"; // 编译错误!
    
            // 非法操作:消息过长(触发校验异常)
            // session.setMessage("超长消息..." + "a".repeat(501)); // 抛出异常
    
            // 展示完整会话信息
            session.showSessionInfo();
        }
    }

      3.3 构造方法详解

      构造方法是 Java 中用于创建对象并初始化成员变量的特殊方法,是面向对象编程中对象生命周期的起点。但是如果咱们没有写jvm(java虚拟机)会自动帮我们生成一个无参构造。

      3.3.1 构造方法的语法规范与作用

      • 方法名必须与类名完全一致(包括大小写)
      • 没有返回值类型(连void都不能写)
      • 创建对象时自动调用:使用new 类名()创建对象时,系统会自动匹配并执行对应的构造方法,完成对象初始化。
      • 给成员变量赋初始值:避免对象创建后成员变量处于默认值(如null0),保证对象创建后即处于可用状态。
      • 执行初始化逻辑:可在构造方法中编写业务逻辑(如生成唯一 ID、记录创建时间等)。
      • 修饰符通常为public,也可根据封装需求使用private/protected
      • 不能被staticfinalabstractsynchronized修饰
      修饰符 类名(参数列表) {
          // 初始化代码
      }
      • 下面代码为一个正确定义的例子:

      public class User {
          // 成员变量
          private String userId;
          private String username;
      
          // 构造方法:与类名同名,无返回值
          public User(String userId, String username) {
              this.userId = userId;
              this.username = username;
              System.out.println("User对象创建成功,初始化完成!");
          }
      }

      3.3.2 构造方法重载:多参数构造的定义、使用场景

      • 一个类中可以定义多个参数列表不同的构造方法,参数列表不同指:参数个数、类型、顺序至少有一项不同,这就是构造方法重载。

      public class User {
          private String userId;
          private String username;
          private int age;
      
          // 无参构造
          public User() {}
      
          // 全参构造
          public User(String userId, String username) {
              this.userId = userId;
              this.username = username;
          }
      
          // 三参构造(重载)
          public User(String userId, String username, int age) {
              this.userId = userId;
              this.username = username;
              this.age = age;
          }
      }
      • 灵活创建对象:根据业务需求选择不同参数的构造方法,比如:
        • 只知道用户 ID 和姓名时,调用User(String, String)
        • 知道完整信息时,调用User(String, String, int)
      • 兼容旧代码:新增字段时,保留原有构造方法,避免修改已有调用逻辑

      3.3.3 默认构造方法的生成与手动定义

      为了保证代码的健壮性和兼容性,推荐手动显式定义无参构造方法,即使它的方法体为空

      • 如果一个类中没有手动定义任何构造方法,编译器会自动生成一个无参的 public 构造方法,方法体为空。
      • 手动定义后失效:一旦手动定义了任意构造方法(有参 / 无参),编译器就不会再自动生成默认构造方法。

      3.4 继承详解

      3.4.1 继承的语法与单继承限制(Java不支持多继承,自身理解限制原因,标注注意事项)

      • 限制 内容 原因解释 注意事项
        单继承 一个类只能直接继承一个父类 Java 为了避免菱形继承问题(两个父类有同名方法,子类不知道调用哪个),保证代码逻辑清晰、安全。 一个类可以有多层继承(如:孙子类 → 子类 → 父类 → Object),但不能同时继承两个平级父类。
        局限性 不能继承构造方法 构造方法用于初始化对象,属于类自己的初始化逻辑,不能被继承。 子类必须通过 super() 显式或隐式调用父类构造。
        访问限制 私有的 (private) 成员不能继承 封装性原则,私有成员仅属于父类自身。 子类可通过 public/getter 方法间接访问私有数据,不能直接访问。
      • //以下为基本定义的格式
        // 父类
        修饰符 class 父类名 {
            // 属性、方法
        }
        
        // 子类(继承父类)
        修饰符 class 子类名 extends 父类名 {
            // 子类特有属性、方法
        }
        // 父类:动物
        class Animal {
            public void eat() {
                System.out.println("动物吃东西");
            }
        }
        
        // 子类:狗(单继承)
        class Dog extends Animal {
            // 子类新增方法
            public void bark() {
                System.out.println("狗汪汪叫");
            }
        }
        //这时候调用子类不仅可以使用bark方法也可以调用eat方法,实现了更详细的使用,也减少了代码的编写。

      3.4.2 super关键字的使用:调用父类构造、成员变量、成员方法(代码示例,自身实操,掌握super的使用规范)

      • super 代表父类对象的引用,用于在子类中访问父类的构造、成员变量、成员方法。

      • 场景一:调用父类构造方法(必须写在子类构造第一行)

      • class Person {
            String name;
            // 父类构造
            public Person(String name) {
                this.name = name;
            }
        }
        
        class Student extends Person {
            int id;
            // 子类构造
            public Student(String name, int id) {
                super(name); // 调用父类有参构造,必须第一行
                this.id = id;
            }
        }
      • 场景二:访问父类成员变量

      • class Base {
            protected String msg = "父类消息";
        }
        
        class Sub extends Base {
            private String msg = "子类消息";
            
            public void show() {
                System.out.println(super.msg); // 访问父类变量
                System.out.println(this.msg);  // 访问子类变量
            }
        }
      • 场景三:调用父类成员方法

      • class Phone {
            public void call() {
                System.out.println("打电话");
            }
        }
        
        class SmartPhone extends Phone {
            @Override
            public void call() {
                super.call(); // 调用父类原方法
                System.out.println("视频通话"); // 新增功能
            }
        }

        使用规范

      • super() 调用构造必须在构造方法第一行,否则编译报错。
      • 用于区分重名变量,明确访问父类成员。
      • 不能在 static 方法中使用 super(static 属于类,super 代表对象)

      3.4.3 方法重写(Override):重写条件、语法规范、@Override注解的使用

      条件 规范 说明
      方法签名一致 方法名、参数列表、返回值类型必须完全相同(JDK1.5 + 支持协变返回)。 这是区分重写与重载的关键。
      访问权限 子类方法权限不能比父类更严格(如父类 public,子类不能 private)。 保证父类功能的可访问性。
      异常 子类方法抛出的异常不能比父类更多。 保证兼容性。
      注解 必须使用 @Override 注解标注(推荐)。 编译器校验,防止拼写错误。
      • 下面是代码示例:

      • class Phone {
            // 父类方法
            public void show() {
                System.out.println("手机展示");
            }
        }
        
        class SmartPhone extends Phone {
            // 重写父类方法
            @Override
            public void show() {
                System.out.println("智能手机展示(新增AI功能)");
            }
        }
      • 重写与重载的区别

      • 对比项 方法重写 (Override) 方法重载 (Overload)
        定义 子类重写父类方法 同一个类中多个方法同名
        参数 必须完全一致 必须不同(个数 / 类型 / 顺序)
        返回值 必须一致(或协变) 无关
        访问权限 不能更严格 无关
        核心目的 扩展、修改父类功能 灵活适配不同参数
      • 3.4.4 继承实操:智能体大模型父类与子类(BaseModel、DoubaoModel,代码+注释,自身编写,重写模型调用方法,贴合智能体场景,巩固继承知识点)

      • /**
         * 3.4.4 继承实操:智能体大模型父类与子类
         *  BaseModel:父类,定义通用模型接口
         *  DoubaoModel:子类,实现具体豆包模型逻辑
         */
        
        // 1. 父类:基础大模型
        class BaseModel {
            protected String modelName;
            
            // 构造方法
            public BaseModel(String modelName) {
                this.modelName = modelName;
            }
            
            // 通用模型调用方法(父类实现)
            public void generateResponse(String prompt) {
                System.out.println("[" + modelName + "] 通用AI回答:" + prompt);
            }
            
            // 模型信息展示
            public void showModelInfo() {
                System.out.println("模型类型:通用大模型");
            }
        }
        
        // 2. 子类:豆包智能体模型(继承BaseModel)
        class DoubaoModel extends BaseModel {
            private String agentVersion; // 豆包特有版本
            
            // 子类构造(调用父类构造)
            public DoubaoModel(String modelName, String agentVersion) {
                super(modelName); // 调用父类构造
                this.agentVersion = agentVersion;
            }
            
            // 3. 重写父类方法:智能体专属逻辑
            @Override
            public void generateResponse(String prompt) {
                // 先调用父类通用逻辑
                super.generateResponse(prompt);
                
                // 新增智能体特有逻辑
                System.out.println("[" + modelName + "-" + agentVersion + "] 智能体推理完成,返回结果");
            }
            
            // 子类特有方法
            public void showAgentInfo() {
                System.out.println("豆包智能体版本:" + agentVersion);
            }
        }
        
        // 3. 测试类
        public class InheritanceDemo {
            public static void main(String[] args) {
                // 创建豆包模型对象
                DoubaoModel doubao = new DoubaoModel("Doubao-Pro", "v3.1.0");
                
                // 调用重写方法
                doubao.generateResponse("介绍一下Java继承");
                
                // 调用子类特有方法
                doubao.showAgentInfo();
            }
        }
        Logo

        有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

        更多推荐