【Java】面向对象基础——继承 + 封装基础题

相信你是最棒哒!!!!!!

文章目录

二、题目代码

1.解析版

2.简洁版

总结


一、题目描述

设计学生类Student包含属性有姓名name和年龄age,由学生类派生出本科生类Undergraduate和研究生类 Graduate。本科生包含的属性有专业specialty,研究生包含的属性有研究方向study_direction ,每个类都有相关数据的toString()输出方法。

二、题目代码

1.解析版

复制代码
// ============ 爸爸类:学生 ============
class Student {

    private String name;   // 私有:只能通过公开方法访问
    private int age;       // 私有:保护数据

    // 构造器:Student s = new Student("张三", 18);时自动跑,负责给姓名、年龄赋初值
    public Student(String name, int age) {
        this.name = name;  // 把形参 name 塞进成员变量 name
        this.age  = age;   // 把形参 age  塞进成员变量 age
    }

    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;    // 你传新年龄,我就覆盖旧的
    }

    // 打印对象时自动调用,决定"长什么样"
    @Override
    public String toString() {
        return "姓名:" + name + ",年龄:" + age;
    }
}

// ============ 大儿子类:本科生 ============
// 关键字 extends 表示"本科生 是 一种 学生",自动拥有爸爸所有非私有成员
class Undergraduate extends Student {

    private String specialty;  // 本科生比爸爸多出来的属性:专业

    // 构造器:先让父类把姓名年龄搞定,再处理自己的专业
    public Undergraduate(String name, int age, String specialty) {
        super(name, age);      // 调用父类的构造器,必须放第一行
        this.specialty = specialty; // 自己的属性自己管
    }

    // 给外部读专业
    public String getSpecialty() {
        return specialty;
    }

    // 给外部改专业
    public void setSpecialty(String specialty) {
        this.specialty = specialty;
    }

    // 打印时先拉父类的信息过来,再拼上自己的特色
    @Override
    public String toString() {
        return "本科生:[" + super.toString() + ",专业:" + specialty + "]";
    }
}

// ============ 二儿子类:研究生 ============
class Graduate extends Student {

    private String researchDirection;  // 研究生比父类多出来的属性:研究方向

    public Graduate(String name, int age, String researchDirection) {
        super(name, age);                // 先让爸爸搞定姓名年龄
        this.researchDirection = researchDirection; // 自己的方向自己存
    }

    public String getResearchDirection() {
        return researchDirection;
    }

    public void setResearchDirection(String researchDirection) {
        this.researchDirection = researchDirection;
    }

    @Override
    public String toString() {
        return "研究生:[" + super.toString() + ",研究方向:" + researchDirection + "]";
    }
}

// ============ 测试入口 ============
public class TestStudent {

    // JVM 启动时唯一入口
    public static void main(String[] args) {

        // 用本科生模板造对象:姓名、年龄、专业 一次给齐
        Undergraduate u = new Undergraduate("张三", 20, "计算机科学与技术");

        // 用研究生模板造对象:姓名、年龄、研究方向 一次给齐
        Graduate g = new Graduate("李四", 25, "人工智能与机器学习");

        // 直接打印对象,会偷偷调用它们各自的 toString() 方法
        System.out.println(u);
        System.out.println(g);

        // 通过 set 方法改内部数据,体现"封装"------外界不直接碰字段
        u.setSpecialty("软件工程");           // 张三转专业
        g.setResearchDirection("大数据分析"); // 李四换方向

        // 再打一次,看改动效果
        System.out.println("\n修改后:");
        System.out.println(u);
        System.out.println(g);
    }
}

2.简洁版

代码如下(示例):

复制代码
class Student {
    private String name;
    private int age;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    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;
    }

    @Override
    public String toString() {
        return "姓名:" + name + ",年龄:" + age;
    }
}

class Undergraduate extends Student {
    private String specialty;

    public Undergraduate(String name, int age, String specialty) {
        super(name, age);
        this.specialty = specialty;
    }

    public String getSpecialty() {
        return specialty;
    }

    public void setSpecialty(String specialty) {
        this.specialty = specialty;
    }

    @Override
    public String toString() {
        return "本科生:[" + super.toString() + ",专业:" + specialty + "]";
    }
}

class Graduate extends Student {
    private String researchDirection;

    public Graduate(String name, int age, String researchDirection) {
        super(name, age);
        this.researchDirection = researchDirection;
    }

    public String getResearchDirection() {
        return researchDirection;
    }

    public void setResearchDirection(String researchDirection) {
        this.researchDirection = researchDirection;
    }

    @Override
    public String toString() {
        return "研究生:[" + super.toString() + ",研究方向:" + researchDirection + "]";
    }
}

public class TestStudent {
    public static void main(String[] args) {
        Undergraduate u = new Undergraduate("张三", 20, "计算机科学与技术");
        Graduate g = new Graduate("李四", 25, "人工智能与机器学习");

        System.out.println(u);
        System.out.println(g);

        u.setSpecialty("软件工程");
        g.setResearchDirection("大数据分析");

        System.out.println("\n修改后:");
        System.out.println(u);
        System.out.println(g);
    }
}

总结

  1. 构造器

    不会点:它到底啥时候跑?

    一句话:new 的一瞬间就跑,用来给对象"接生+建档"。

    口诀:new 必调构造,无构造系统送,有构造自己写。

  2. this.name = name

    不会点:左边右边都是 name,到底谁是谁?

    一句话:左边是"对象自己的小抽屉",右边是"外人递进来的纸条"。

    口诀:this.成员 = 参数,把纸条塞进抽屉。

  3. private 的真正意义

    不会点:为啥不能直接 .name

    一句话:private 是保险柜,钥匙只给 get/set,以后想加校验不换锁。

    口诀:私有防黑手,通道留门口。

  4. extends 到底继承了啥

    不会点:"所有非私有成员"是哪部分?

    一句话:除了 private 的字段/方法,其余 public/protected/包私有 全白嫖。

    口诀:私有不继承,其余全白送。

  5. super(...) 必须第一行

    不会点:为啥不能放第二行?

    一句话:先让爸爸把地基打好,儿子再装修;Java 强制顺序。

    口诀:super 先老爸,再搞自己。

  6. @Override 是干啥

    不会点:不写也能跑,写它干嘛?

    一句话:写错方法名时编译器立刻报错,防止"以为重写、其实新建"的乌龙。

    口诀:Override 护身符,写错就红叉。

  7. System.out.println(对象) 为啥能输出人话

    不会点:我没调 toString() 啊?

    一句话:println 会自动找对象的 toString(),没重写就打印"类名@哈希码"。

    口诀:打印对象=自动 toString,重写就能说人话。

  8. set 方法的意义

    不会点:直接改字段更快,为啥多此一举?

    一句话:以后想加"年龄不能为负""专业必须来自字典"等校验,只改 set 即可,外部代码零变动。

    口诀:今天直接改,明天需求哭;通道留一手,维护不跳楼。

  1. 你在 main 里写

    复制代码
    Student s = new Student("张三", 18);
  2. JVM 一看 new,立刻做三件事:

    a. 在内存堆区给新对象划一块地皮。

    b. 在这片地里先建一个"空壳",字段全是默认值(name=null, age=0)。

    c. 马上自动调用 public Student(String name, int age) ------ 这就是构造器。

    构造器把 "张三"18 分别塞进 nameage,壳子瞬间变成有血有肉的对象。

  3. 构造器跑完,对象返回给你,s 变量才拿到真正的"学生身份证"。

extends 之后,子类自动拿到爸爸下面这些东西:

  1. public 成员------随便用。

  2. protected 成员------同包或子类里直接用。

  3. 包私有成员(没写修饰符)------只要子类和爸爸在同一个包,也能直接用。

不会拿到的是:

  • private 字段 / 方法 ------ 爸爸锁在保险柜里,儿子看不见,更摸不着。

    如果儿子非要玩,只能走爸爸提供的 public/protected 方法(例如 getName()/setName())去间接访问。

代码看过程:

复制代码
class Dad {
    private String secret = "爸爸私房钱";   // 儿子看不见
    public String getSecret() {            // 官方复印机
        return secret;
    }
}

class Son extends Dad {
    void play() {
        // System.out.println(secret);     // ❌ 直接摸会报错
        System.out.println(getSecret());  // ✅ 走爸爸提供的公开方法,拿到副本
    }
}

所以"间接访问"就是:儿子不碰保险箱,只按爸爸提供的按钮,让爸爸代劳取/放

相关推荐
心疼你的一切1 小时前
Unity开发Rokid应用之离线语音指令交互模型
android·开发语言·unity·游戏引擎·交互·lucene
N***73851 小时前
JavaScript物联网案例
开发语言·javascript·物联网
IT方大同1 小时前
C语言的组成部分
c语言·开发语言
BINGCHN1 小时前
流量分析进阶(一):RCTF2025-Shadows of Asgard
开发语言·python
G***66912 小时前
Java区块链开发
java·开发语言·区块链
Java天梯之路2 小时前
上篇讲坑,这篇讲 “根”!Java 数据类型底层逻辑全解析
java·面试
悟空码字2 小时前
手把手搭建Java微服务:从技术选型到生产部署
java·后端·微服务
leonardee2 小时前
MySQL----case的用法
java·后端
慧慧吖@2 小时前
Zustand
开发语言·javascript·ecmascript