ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

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

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.formatSystem.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(张三); // NullPointerExceptionnew 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面向对象里非常经典的考点了到了函数题里也会以“判断两个对象是否相等”的形式出现。基础类型用比较值对象类型用比较的是引用也就是两个变量是否指向同一块堆内存。函数题里大多数情况是两个对象内容相同就算相等。最稳妥的实现方式是重写equalspublic 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的时候是这样操作的把题面给出的主函数代码完整复制到本地IDEA一个Main.java文件里。根据主函数的调用先写出类的基本骨架字段构造方法签名。在本地写完所有代码自己跑一遍确认输出正常。提交时只复制“类定义部分”不复制主函数类。这个流程看起来多了一步但能帮你拦住80%的编译错误。因为OJ的报错只有一行英文你很难看出自己的类是不是写错了但本地IDEA右下角红色波浪线直接告诉你哪一行出了问题。4.2 自己构造测试输入覆盖边界值只跑题目样例远远不够。我自己的经验是样例能过往往只是运气好OJ的测试点比你想象的狠如果题面说成绩是整数你至少要测一次0分和一次100分。如果日期类要求判断合法性测一下2月29日闰年和平年各一次。如果一个类设计了setRadius测一次传入负数看你的方法有没有做出合理反应。很多答案错误WA就是死在边界值上。比如月薪计算题有人没处理“天数为0”有人没处理“离职当月只按15天算”这种测试点一打一个准。函数题不会明着告诉你需要处理边界但题面如果有“如果输入不合法返回-1”这类描述千万别忽视。4.3 提交前删掉所有调试输出本地跑的时候我习惯加System.out.println看中间变量比如打印一下radius、打印一下score这很正常。但如果提交前忘了删OJ就会把你的调试输出当成答案的一部分和期望输出匹配不上必然WA。这里有个经验你可以把所有调试输出统一放在一个固定位置提交前CtrlF搜一下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对你来说是第一次接触函数题我的建议是别按题号顺序刷按类型刷先做最简单的“学生类”“员工类”这类纯数据类题目把类、构造、封装的流程跑通。再做“圆类”“矩形类”这种带计算逻辑的题目重点解决输出精度和计算式。最后做日期类和对象数组题这种综合性最强需要在边界条件和引用对象上多花心思。按难度递进的最大好处是你不会在前几题就被打击到失去兴趣。很多同学做这类作业往往是第一题卡了很久后面就放弃了实际上第一题卡不是因为难而是因为不熟悉函数题的“答题姿势”。一旦姿势对了后面都是一路畅通。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、写成了。把小事先排干净再去纠结算法和逻辑。函数题考的就是面向对象的基础素养这些素养就藏在这些“小事”里。
返回列表