news 2026/10/8 3:25:42

Java面向对象函数题23-34:类、对象与构造方法补全技巧

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Java面向对象函数题23-34:类、对象与构造方法补全技巧

又到了《Java面向对象》第五章的作业时间。如果你正在刷“sdut-Java面向对象-05 类和对象(函数题:23-34题)”,大概率已经被题目框里那几段残缺代码折腾得有点上头:明明上课听懂了什么是类、什么是对象,真到了OJ上,却连一个构造方法都补不完整,要么报“找不到符号”,要么答案错误。这篇就是解决这个问题的。

我会围绕“类和对象”这个核心,把函数题 23-34 的命题逻辑、补全技巧和踩坑点完整拆一遍,适合三大人群:正在做这组作业的大学生、准备Java基础面试的求职者、以及刚学完封装但做题总WA的初学者。看完你不会成为理论大师,但至少能把这12道函数题稳定拿分。

1. 函数题真正的玩法:它不是让你写整个程序

1.1 先看懂题面给了你什么

函数题和编程题最大的区别在于:OJ已经帮你写好了主程序和一部分类结构,你只需要补上指定的方法、构造器或字段。

我见过很多第一次做函数题的同学,直接往答题框里扔了一整个public class Main,结果编译直接挂了。原因很简单:系统会把你的代码和它隐藏的主程序拼接在一起再编译,你重复定义了Main类,两个类撞在一起,不报错才怪。

所以拿到题的第一件事,不是开写,而是读:

  • 题面开头通常有一段“已有代码”或“参考代码”,看清楚哪些方法已经有了签名,哪些只有注释没有实现。
  • 注意题目说明,比如“请补全Circle类的构造方法,使得主函数能正确创建对象”。这句话已经告诉你,要写的部分是构造方法,而不是getArea()。
  • 把题面中的类名、方法名原样复制进答题框,哪怕你觉得它命名不规范也别改——OJ的测试程序是按名字反射调用的,名字错一个字母就是“找不到符号”。

1.2 补全类和补全方法的两种姿势

函数题有两种常见形态,应对方法不一样。

第一种是补全函数的题。题目给了一个类,里面有一个残缺的方法,比如:

class Calculator { public int add(int a, int b) { // 请在这里实现加法 } }

这种最直接,你把return a + b;填上就行,不需要动其他部分。但要注意方法和变量作用域,别在方法内部随便声明一个同名局部变量把参数盖住。

第二种是补全整个类的题。题目只给你主函数代码,让你把Circle、Student、Date这类类整体补出来。这种题在23-34里更常见,需要你根据主函数的调用方式来反推类的结构。比如主函数里有new Circle(2.5),那就必须有一个带double参数的构造方法;如果你只写了一个无参构造器,等着你的就是“构造函数无法应用”。

1.3 23-34这批题目的常见骨架

如果你把这12道题铺开看,会发现命题人没什么新招,就是Classic三件套:

  • 描述现实实体的类:人、学生、银行账户、图书、手机。
  • 几何计算类:圆、矩形、三角形、线段。
  • 日期时间类:日期合法性、天数差、具体星期几。

这类题的主函数无非是“创建对象 → 调用方法 → 输出结果”。所以你的类只要满足主函数调用链,基本就能拿分。

2. 这12道题命题者想考的四块骨头

2.1 类设计型:字段、构造、方法的默认约定

类设计型题目是最多的,比如“定义一个学生类,包含学号、姓名、成绩三个字段,要求能创建对象并输出信息”。这类题考的不是你会不会写代码,而是你有没有遵守Java的类设计约定。

一个完整的最小类长这样:

class Student { private String id; private String name; private double score; public Student(String id, String name, double score) { this.id = id; this.name = name; this.score = score; } public String getId() { return id; } public void setId(String id) { this.id = id; } // getName/setName、getScore/setScore 同理 public String toString() { return id + " " + name + " " + score; } }

有几个注意点:

  • 字段必须是private,除非题面明确要求public。这是面向对象封装的基本要求,也是OJ判分时偶尔人工审题的部分。
  • 构造方法名必须和类名完全一致,首字母大小写都不能差。
  • 写了带参构造之后,无参构造不会自动存在。如果主函数里用了new Student(),你又只写了new Student(...),会直接编不过。解决方案是自己再补一个无参构造。

2.2 封装型:为什么私有字段必须配 getter/setter

封装这个知识点,在函数题里最常见的考法是:题目把字段设成private,然后在主函数里通过getId()、setScore()这样的方法访问。如果你只定义了私有字段却没写公共方法,主函数一编译就是“id 在 Student 中是 private 访问控制”。

我的习惯是看到private字段,立刻成套写出 getter 和 setter,甭管题面有没有用到一半。因为有时候主函数第一版没用,测试点第二组数据却用了。反正也就几行代码,多写不扣分,少写必WA。

setter 里还有个容易翻车的点:方法不能有返回值。我记得有一次批改同学代码,他写的是public boolean setAge(int age),然后函数体内return true;。语法上没错,但主函数调用stu.setAge(18)的预期根本没人接收返回值,方法签名对不上就编译失败。setter 老老实实void,别发挥。

2.3 计算型类:几何和日期类的输出格式陷阱

几何题和日期题除了考类设计,还考数值计算和格式控制。

几何题常见的坑是这个:**圆周率用Math.PI,而不是自己写3.14。**你写3.14,前几个测试点可能对,一旦题目要求输出到小数点后两位,误差立刻暴露,结果WA。Math.PI精度足够,直接用。

日期题更像是一个边界条件收集器。判断日期合法性时,至少要考虑:

  • 年份最小为1,月份在1到12之间。
  • 日的上限要按月份区分,尤其二月——闰年29天,平年28天。
  • 闰年判断标准:能被4整除但不能被100整除,或者能被400整除。

输出格式方面,很多题要求“保留两位小数”或“日期格式为yyyy-MM-dd”。推荐直接用String.format:

System.out.println(String.format("%.2f", area)); System.out.println(String.format("%04d-%02d-%02d", year, month, day));

%04d这个写法能让月份和日期自动补零,比如2024-01-05,不会输出成2024-1-5。

2.4 对象数组与引用型:null和销毁问题

23-34后期一定有对象数组的题,通常是这样:读入n个学生信息,存入对象数组,然后按成绩排序或输出。这里最经典的错误是忘记给数组里的每个元素单独new。

Student[] students = new Student[3]; students[0].setName("张三"); // NullPointerException!

new Student[3]只是创建了一个长度为3的引用数组,里面每个位置默认是null。你必须先循环:

for (int i = 0; i < n; i++) { students[i] = new Student(); }

然后再调用方法。这个坑能卡住相当一部分人,而且报错信息还比较隐蔽,看起来很像是“数组越界”或者“对象没建”。

此外对象比较也有讲究。函数题里偶尔会出现“判断两个日期对象是否相同”之类的需求。如果你写date1 == date2,那比较的是引用地址,不是内容。大多数情况下题目希望你重写equals方法,或者逐个比较字段。我一般建议直接比较字段值,简单不易错。

3. 类和对象底层逻辑:老师不讲但你绕不开的几个点

3.1 成员变量默认值和初始化时机

函数题最常见的初始化戏法就是“故意不给你构造方法,让你猜成员变量的初值”。Java成员变量有默认值:整型是0,浮点型是0.0,布尔型是false,引用类型是null。

这意味着:

class Counter { private int count; // 没有写构造方法 }

主函数直接new Counter()也能编译,count的最初值是0。有些题利用这点,让你补一个increment()方法,在原来的0基础上加1。你要是非得写个构造器把count初始化为1,恭喜,答案错。

局部变量则完全不同,没有默认值,不赋值直接用就会编译报错“可能尚未初始化”。我当时刷题时经常把这两者搞混,所以特意提醒一下:方法内部的变量,必须显式初始化。

3.2 this 到底是谁

this在函数题里的核心用途就两个:给成员变量传值、调用本类的其他构造器。

第一种最常用,因为构造函数参数名经常和字段名重名:

public void setName(String name) { this.name = name; }

去掉this.,就变成了把参数赋给参数自己,成员变量什么都没变。这种Bug编译器不报错,因为它合法,但你的对象字段永远是null或0。

第二种用在构造器重载场景。假如题里既要支持new Student(),又要支持new Student("张三", 90),可以这样:

public Student() { this("无名", 0); } public Student(String name, double score) { this.name = name; this.score = score; }

无参构造里调用this(...)必须写在第一行,这算语法硬性要求。它的作用是让无参构造复用带参构造的初始化逻辑,省得写两遍。

3.3 构造方法和普通方法的区别

函数题里很容易把构造方法写成普通方法,多写一个void或者写错了返回类型。构造方法不能显式声明返回值类型,连void都不能写。

public Student(String name) { // 这是构造方法,正确 this.name = name; } public void Student(String name) { // 这是普通方法,但名字和类名相同,非法! this.name = name; }

第二种写法编译会直接提示“方法名冲突”,或者干脆被认为是“无效的方法声明”。我见过一位同学在补全构造器时多打了个空格,类名和方法名长得一样,OJ报错“非法开始表达式”,整整找了三十分钟。

3.4 对象的比较:== 和 equals 不可混用

这算是Java面向对象里非常经典的考点了,到了函数题里也会以“判断两个对象是否相等”的形式出现。基础类型用==比较值,对象类型用==比较的是引用,也就是两个变量是否指向同一块堆内存。

函数题里大多数情况是两个对象内容相同就算相等。最稳妥的实现方式是重写equals:

public boolean equals(Student other) { if (other == null) return false; return this.id.equals(other.id) && this.name.equals(other.name); }

注意字符串比较也要用equals,不能==。这块是面试高频,也是现在刷题的高频,专门写在提醒清单里。

4. 本地模拟OJ测试的完整流程

4.1 把题目代码完整粘贴进本地IDE

函数题正确姿势从来不是直接在答题框里盲写。我刷23-34的时候是这样操作的:

  1. 把题面给出的主函数代码完整复制到本地IDEA一个Main.java文件里。
  2. 根据主函数的调用,先写出类的基本骨架(字段+构造方法签名)。
  3. 在本地写完所有代码,自己跑一遍,确认输出正常。
  4. 提交时只复制“类定义部分”,不复制主函数类。

这个流程看起来多了一步,但能帮你拦住80%的编译错误。因为OJ的报错只有一行英文,你很难看出自己的类是不是写错了;但本地IDEA右下角红色波浪线直接告诉你哪一行出了问题。

4.2 自己构造测试输入,覆盖边界值

只跑题目样例远远不够。我自己的经验是,样例能过,往往只是运气好,OJ的测试点比你想象的狠:

  • 如果题面说成绩是整数,你至少要测一次0分和一次100分。
  • 如果日期类要求判断合法性,测一下2月29日(闰年和平年各一次)。
  • 如果一个类设计了setRadius,测一次传入负数,看你的方法有没有做出合理反应。

很多答案错误(WA)就是死在边界值上。比如月薪计算题,有人没处理“天数为0”,有人没处理“离职当月只按15天算”,这种测试点一打一个准。函数题不会明着告诉你需要处理边界,但题面如果有“如果输入不合法,返回-1”这类描述,千万别忽视。

4.3 提交前删掉所有调试输出

本地跑的时候,我习惯加System.out.println看中间变量,比如打印一下radius、打印一下score,这很正常。但如果提交前忘了删,OJ就会把你的调试输出当成答案的一部分,和期望输出匹配不上,必然WA。

这里有个经验:你可以把所有调试输出统一放在一个固定位置,提交前Ctrl+F搜一下println,看除了题目要求的输出以外还有没有多余的。我因为这种东西在别的题目上WA过至少两次,后来就养成了提交前强制搜索的习惯。

另外,函数题里你补全的方法一般不需要自己println,只需要return一个值。主函数会负责打印。很多同学习惯性地在方法里System.out.println(...),结果输出格式错乱,直接答案错误。

5. 提交之后常见报错全排查

5.1 编译错误:找不到符号、构造器冲突、类重复

在OJ上编译错误(CE)是最让人烦的,因为报错信息还简略。我总结出三个最常出现的编译错误及对应解法:

报错片段原因解法
cannot find symbol类名或方法名拼写错误,字段不在你写的类里逐字对照题面代码,尤其注意大小写
constructor X cannot be applied to given types主函数要求的构造器参数和你的不一致检查构造器参数类型和数量,必要时补全无参构造
class Main is already defined你多写了一个Main类删除自己的主类,只提交类定义

cannot find symbol这个错误我见得最多,一半以上是因为写错单词,比如getArae()这种手误。所以如果你看到这个报错,先不要怀疑玄学,回去看看题面方法签名是不是多了一个字母。

5.2 运行错误:NullPointerException 和数组越界

函数题里的运行错误(RE)主要就两种。

NullPointerException最常见的来源有两个:一是对象数组里的元素没有new,前面已经说过;二是你返回或访问了一个null对象的字段。比如题面让你“根据学号查询学生”,如果查不到,可能要求你返回null,而主函数拿到null后调用了.getName(),就炸了。

数组越界则多发生在日期题里。比如你想把月份对应的天数存到一个数组里:

int[] days = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

如果你直接用days[month],而month从1开始编号,1月会取出31,但12月会越界。正确做法是days[month - 1],或者在访问前先判断month的范围。

5.3 答案错误:精度、格式、多余输出

答案错误(WA)是函数题的另一种主旋律,而且往往最憋屈,因为代码能跑,只是输出某个字符不对。

最隐蔽的是精度问题。几何题要求保留两位小数,你用Math.round(area * 100) / 100.0,看起来好像“更准确”,但OJ期望的可能是printf("%.2f")的四舍五入规则。两者在逢5进位时有时表现不一致。我建议纯输出类问题一律用printf或String.format,不要自己手写四舍五入逻辑。

多余输出我已经在前面说过,这里再补一个细节:末尾换行。有些题目明确要求每个结果占一行,主函数可能已经输出了println,你补全的方法里就千万别再加换行了。多个\n看似不影响阅读,但OJ的判题是逐字符比对的,多出来的一个换行符就是WA。

6. 刷完23-34之后你该有的“类设计直觉”

6.1 一个类的健康检查标准

连续刷完这12道题后,你看到一道函数题,应该能在30秒内做出一个判断:题目需要的是一个纯数据类(只有字段和getter/setter),还是一个行为类(字段+计算逻辑),还是一个工具类(全是静态方法)。

判断方法很简单:看主函数怎么用。

如果主函数创建对象后只调用get/set,那就是纯数据类。如果创建对象后调用了getArea()、getTotalSalary(),那就是行为类,需要把计算逻辑封装进类里。

我建议你在提交前按这个清单自查:

  • 类名和文件名是否一致,类名首字母是否大写。
  • 所有字段是否符合题面要求的访问修饰符。
  • 带参构造器是否覆盖了主函数会调用的所有参数组合。
  • 需要toString或equals的地方有没有实现,实现时输出格式是否和样例一致。
  • 方法内部有没有println,如果只需要返回值就删掉。

6.2 做题顺序建议和现场检查节奏

如果23-34对你来说是第一次接触函数题,我的建议是别按题号顺序刷,按类型刷:

  1. 先做最简单的“学生类”“员工类”这类纯数据类题目,把类、构造、封装的流程跑通。
  2. 再做“圆类”“矩形类”这种带计算逻辑的题目,重点解决输出精度和计算式。
  3. 最后做日期类和对象数组题,这种综合性最强,需要在边界条件和引用对象上多花心思。

按难度递进的最大好处是,你不会在前几题就被打击到失去兴趣。很多同学做这类作业,往往是第一题卡了很久,后面就放弃了,实际上第一题卡不是因为难,而是因为不熟悉函数题的“答题姿势”。一旦姿势对了,后面都是一路畅通。

6.3 补全类时先写出方法签名再填内容

这里分享一个我实际写题时的小技巧:先把所有方法签名空着填好,再逐行写函数体。

比如说题目要你写一个Circle类,主函数里有这几行:

Circle c = new Circle(2.5); double area = c.getArea(); double perimeter = c.getPerimeter();

你先在类里写:

class Circle { private double radius; public Circle(double r) { } public double getArea() { } public double getPerimeter() { } }

这个时候编译虽然报错(方法体没返回),但你已经搭好了框架,剩下的工作只是往每个方法里填计算式子。这样做比一边想字段一边想构造一边想计算公式要快得多,也更容易检查接口是否满足主函数调用。

6.4 刷完这套题后,你其实已经学会了什么

这12道函数题做完,你可能觉得:“这不就是写一堆模板类吗?”但从面试角度来看,这些题目恰恰覆盖了Java面向对象最重要的基本功:封装思想、构造器重载、this的使用、对象数组管理、引用传递和边界处理。

我做Java这么多年,面试新人时最怕的不是他不会Spring、不会MyBatis,而是他写一个最基础的Student类都漏getter、setter,或者在equals里写出==。23-34这组题就像是提前把这些坑都踩了一遍,刷完后再写任何实体类,肌肉记忆都会逼你把字段设成private、构造器补全、明明方法签名确认一遍。

最后再说一件我自己经历过的事:当年刷这种函数题,我有一道题怎么都WA,本地测了七八组数据全都正常,提交上去怎么都是“答案错误”。后来才发现,我为了调试方便,在getArea()里顺手写了一句System.out.println("radius = " + radius),忘了删。交叉看一遍,这段调试代码赫然躺在答题框里。删掉重交,一次过。

所以,如果这一类题再卡你,请先怀疑这些“小事”:多余的输出、多一个换行、少一个return、写成了==。把小事先排干净,再去纠结算法和逻辑。函数题考的就是面向对象的基础素养,这些素养就藏在这些“小事”里。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/8 3:25:11

商场火灾自动报警系统设计全解析:从点位计算到联动调试

做消防设计这些年&#xff0c;最常被问到的问题就是“商场火灾自动报警系统到底怎么做”&#xff0c;尤其是碰到综合体里某一层或某一区单独改造、单独验收时&#xff0c;很多新入行的朋友容易把规范条文背得滚瓜烂熟&#xff0c;到了画图和算点位时还是不知道从哪里下手。这篇…

作者头像 李华
网站建设 2026/10/8 3:24:51

Agent-Reach 实战:从零搭建轻量级 AI Agent 命令行工具

1. 从零认识 Agent-Reach&#xff1a;一个把 AI Agent 落到实处的命令行工具Agent-Reach 这个名字第一次出现在我视野里的时候&#xff0c;我正被一堆 AI Agent 的框架文档折磨得头大。市面上的 Agent 方案要么是重型框架&#xff0c;装完依赖就得半小时起步&#xff1b;要么是…

作者头像 李华
网站建设 2026/10/8 3:24:27

Spring Boot异步任务超时控制实战:从@Async到可配置超时机制

Spring Boot 的Async注解用得爽&#xff0c;但超时控制这事&#xff0c;十个项目有九个是裸奔的。异步任务一旦卡死&#xff0c;既没有报错&#xff0c;也没有后续处理手段&#xff0c;线程池资源被白白占着&#xff0c;上游接口等不到结果一直转圈。我在好几个项目里都踩过这个…

作者头像 李华
网站建设 2026/10/8 3:24:11

Mac mini私有RAG实战:轻量架构实现高准度本地知识检索

1. 为什么Mac mini是私有RAG知识库的“隐形冠军”——不是性能最强&#xff0c;而是平衡性最优你可能已经看过太多用3090、A100甚至整机柜GPU搭建RAG的教程&#xff0c;但真正把知识库部署进办公室、书房、实验室&#xff0c;甚至塞进抽屉角落的&#xff0c;往往是那台安静得几…

作者头像 李华
网站建设 2026/10/8 3:23:08

AI Agent 触达能力落地:从工具注册到调用观测的工程实践

如果你最近在做 AI Agent 相关的应用&#xff0c;多半会撞见一个尴尬场景&#xff1a;模型对答如流&#xff0c;说了一堆方案&#xff0c;却没法真正把手头的事办成。你可能也经历过类似对话——问 Agent“帮我查一下最近一版订单到哪了”&#xff0c;它回了一句“好的&#xf…

作者头像 李华
网站建设 2026/10/8 3:22:31

OpenMontage:面向AI Agent的视频编排操作系统

1. OpenMontage不是另一个AI视频工具&#xff0c;而是Agent时代的内容编排操作系统OpenMontage这个名字刚出现在GitHub Trending榜上时&#xff0c;我第一反应是——又一个打着“开源”旗号的视频剪辑Web应用&#xff1f;直到我花三小时跑通它的本地demo&#xff0c;才意识到自…

作者头像 李华