Java基础入门课后题答案:从HelloWorld到JDBC的代码级拆解

发布时间:2026/11/3 11:23:09
Java基础入门课后题答案:从HelloWorld到JDBC的代码级拆解 简介这份文档面向Java初学者与高校学生针对《Java基础入门》教材课后习题提供系统参考答案帮助读者在学完每章后及时核对思路、巩固语法与面向对象概念。压缩包内共1个doc文件约214KB按章节组织填空、判断、选择、简答与编程题答案覆盖Java开发入门、语言基础、程序设计及面向对象编程等模块并附HelloWorld、奇数求和、数组排序、学生类封装等编程题参考代码。已有5695人学习下载适合课堂配套练习、期末复习与自学自查可对照简答要点理解JRE与JDK区别、短路运算符、方法重载、构造方法及封装继承多态等高频考点也能借助编程题示例梳理编译运行流程与代码书写规范快速定位薄弱环节并查漏补缺。1. 一份课后题答案为什么值得当成“可执行规格书”来读带过几届新人之后我发现一个反直觉的现象真正把 Java 基础打牢的人往往不是刷题最多的而是会把课后题答案逐行跑一遍、再故意改坏它看报错的那批人。这份《Java 基础入门》课后习题答案覆盖第 1 章到第 9 章从 JDK/JRE 关系到八种基本数据类型、从短路到方法重载、从集合去重到 JDBC 六步走题目和参考答案是成对出现的。它解决的不是“答案在哪”而是“每个知识点在代码里长什么样”。适合正在自学 Java 后端、准备面试八股、或者带新人需要一份对照清单的从业者。下面我按“先跑通、再拆解、最后避坑”的顺序把它当成一份可复现的规格书来拆。2. 从 HelloWorld 到字节码把第 1 章的编译链路跑通第 1 章看着最水其实藏着后面所有章节的地基。填空题里 Java EE / Java SE / Java ME 的三分法、JRE 与 JDK 的包含关系、javac与java两个命令的分工简答题里“先编译成 .class 再由 JVM 解释执行”的两步流程这些如果只是背下来遇到NoClassDefFoundError或UnsupportedClassVersionError时照样抓瞎。我的做法是把这一章当成一次环境自检不装 IDE纯命令行走一遍把每个报错都当成知识点来读。2.1 用命令行复现编译与运行两步先把参考答案里的 HelloWorld 原样落地注意文件名必须和 public 类名一致这是 Java 的硬约束不是风格建议。# 目录结构建议每章一个文件夹避免 classpath 混乱 mkdir -p ch01 cd ch01 # 写入源文件文件名必须与 public class 名完全一致 cat HelloWorld.java EOF public class HelloWorld { public static void main(String[] args) { System.out.println(这是第一个 Java 程序!); } } EOF # 第一步编译生成 HelloWorld.class 字节码 javac HelloWorld.java # 第二步运行注意这里写的是类名不带 .class 后缀 java HelloWorldjavac负责把.java编译成.classjava负责启动 JVM 加载并解释执行字节码这正是第 1 章简答题第 3 问的原文逻辑。参数上要留意两点javac -d out HelloWorld.java可以把字节码输出到指定目录配合java -cp out HelloWorld使用这是后面多包结构项目的必备姿势java -version和javac -version的版本号必须一致不一致就是典型的“编译用高版本、运行用低版本”会直接抛UnsupportedClassVersionError。2.2 用 PATH 与 CLASSPATH 验证第 1 章填空题填空题里bin目录、path、classpath三个空很多人填对了但没真正理解。PATH决定系统去哪找javac.exe/java.exe这些可执行程序CLASSPATH决定 JVM 去哪找.class文件。验证方法很直接临时清空CLASSPATH在非当前目录下运行看它是否还能找到类。# 查看当前 JAVA_HOME 与 PATH 是否指向同一个 JDK echo $JAVA_HOME which javac which java # 故意在别的目录运行观察 classpath 行为 cd /tmp java -cp /path/to/ch01 HelloWorld # 显式指定 classpath能跑通 java HelloWorld # 不指定通常报 Could not find or load main class这里的关键认知是CLASSPATH不配也能跑是因为现代 JDK 默认把当前目录.算进去一旦项目有了包名package com.xxx;当前目录就不再是类的根路径必须用-cp指到包的父目录。第 1 章那些看似死记硬背的填空本质是在给你一张“出问题时先查哪里”的地图。3. 基本类型、短路运算与重载第 2 章的三个高频翻车点第 2 章是整份答案里信息密度最高的一章。八种基本数据类型及字节数、与的区别、方法重载的判定规则这三块几乎每次面试都会碰到而且都能用极短的代码复现出“看起来对、跑起来错”的效果。我一般会让新人先把这三段代码手敲一遍不许复制敲完再对照答案看差异。3.1 八种基本类型的字节数与取值范围实测简答题第 1 问列了 byte/short/int/long/float/double/char/boolean 的字节数但“boolean 占一个字节”这个说法在不同 JVM 实现里其实有争议规范只保证它能表示 true/false。与其纠结不如用代码把边界值打出来形成肌肉记忆。public class PrimitiveBounds { public static void main(String[] args) { // 整型的边界注意 int 字面量溢出会直接编译报错 System.out.println(byte: Byte.MIN_VALUE ~ Byte.MAX_VALUE); System.out.println(short: Short.MIN_VALUE ~ Short.MAX_VALUE); System.out.println(int: Integer.MIN_VALUE ~ Integer.MAX_VALUE); System.out.println(long: Long.MIN_VALUE ~ Long.MAX_VALUE); // 浮点型没有精确边界用 MIN_VALUE/MAX_VALUE 看的是可表示的最小正数/最大数 System.out.println(float: Float.MIN_VALUE ~ Float.MAX_VALUE); System.out.println(double: Double.MIN_VALUE ~ Double.MAX_VALUE); // char 是无符号 16 位范围 0 ~ 65535 System.out.println(char: (int) Character.MIN_VALUE ~ (int) Character.MAX_VALUE); // 经典陷阱两个 int 相加溢出结果变负数 int a Integer.MAX_VALUE; System.out.println(溢出演示: (a 1)); } }这段代码的价值在于把“字节数”翻译成“边界值”。int是 4 字节、32 位所以最大值是 2^31-1long是 8 字节赋值时字面量要加L后缀否则long x 9999999999;会编译失败因为右边默认按 int 解析已经溢出。float只有 4 字节却要表示很大范围代价是精度只有约 7 位有效数字这也是为什么金额计算一律用BigDecimal而不是double——这条经验第 2 章没写但它是从“字节数”这个知识点自然推出来的。3.2与的短路差异用除零异常验证简答题第 2 问讲得很清楚两边都算左边为 false 就短路。原文给的例子是x y x / 2 0会触发除零异常。这里有个细节要注意原文例子里写的是x / 2但描述里说的是“被 0 除”实际要触发异常得让除数是 0。我把它改成可运行的版本顺便把|和||也一起验证了。public class ShortCircuitDemo { public static void main(String[] args) { int x 2, y 0; // 非短路 右边 x / y 一定会执行y 为 0 直接抛 ArithmeticException try { boolean b1 x y x / y 0; System.out.println(b1 b1); } catch (ArithmeticException e) { System.out.println( 触发了除零异常: e.getMessage()); } // 短路 左边 x y 为 false右边根本不执行安全 boolean b2 x y x / y 0; System.out.println( 结果 b2 没有异常); // 同理验证 | 与 || try { boolean b3 x y | x / y 0; System.out.println(b3 b3); } catch (ArithmeticException e) { System.out.println(| 触发了除零异常: e.getMessage()); } boolean b4 x y || x / y 0; System.out.println(|| 结果 b4 没有异常); } }运行结果会明确告诉你和|是位运算符兼逻辑运算符用在 boolean 上不做短路和||才是短路逻辑运算符。实际开发里判断对象非空再取属性obj ! null obj.getName() ! null这种写法能跑换成就可能 NPE这就是“知道区别”和“用对区别”的差距。参数上没什么可调的但要注意短路顺序会影响副作用如果右边表达式带赋值或方法调用短路与否直接决定它执行不执行。3.3 方法重载的判定只有参数列表算数简答题第 3 问说重载是“同名方法、参数个数或类型不同”。这句话漏了关键边界返回值类型不同不构成重载参数名不同也不构成重载只有参数列表个数、类型、顺序不同才算。下面这段代码把合法与非法两种情况都摆出来。public class OverloadDemo { // 合法重载参数个数不同 public int sum(int a) { return a; } public int sum(int a, int b) { return a b; } // 合法重载参数类型不同 public double sum(double a, double b) { return a b; } // 合法重载参数顺序不同 public String sum(String s, int n) { return s n; } public String sum(int n, String s) { return n s; } // 非法仅返回值不同编译直接报错下面这行放开就编译不过 // public double sum(int a, int b) { return a b; } public static void main(String[] args) { OverloadDemo d new OverloadDemo(); System.out.println(d.sum(1)); // 命中 sum(int) System.out.println(d.sum(1, 2)); // 命中 sum(int,int) System.out.println(d.sum(1.0, 2.0)); // 命中 sum(double,double) System.out.println(d.sum(x, 1)); // 命中 sum(String,int) } }JVM 在编译期就根据实参的静态类型完成方法绑定这叫静态分派所以重载是“编译期多态”和后面第 4 章的重写运行期多态是两回事。容易翻车的点是自动类型提升d.sum(1, 2)如果只有sum(double,double)一个候选int 会被提升成 double 去匹配结果可能和预期不符有精确匹配时优先精确匹配。这也是为什么重载设计要避免“只差一个类型宽度”的版本否则调用方永远猜不到命中了哪个。4. 面向对象两章封装、继承、多态在代码里的真实边界第 3、4 章合起来是面向对象的上下篇答案里既有概念简答也有 Student 类、图形接口这类编程题。这两章最容易被当成“背概念”但真正拉开差距的是访问修饰符的可见范围、构造方法与普通方法的调用时机、重写与重载的区别、抽象类与接口的选型。我习惯把这两章的编程题当成一个小型重构练习先按答案写再故意破坏封装看编译器怎么拦。4.1 四种访问修饰符的可见范围用代码验证填空题第 3 问列了 private、default、protected、public 四个修饰符简答题讲封装是“隐藏实现细节”。光背表格没用得让编译器亲口告诉你边界在哪。下面用同包和跨包两个类来验证。// 文件pkg1/Base.java package pkg1; public class Base { private int a 1; // 仅本类可见 int b 2; // default仅同包可见 protected int c 3; // 同包 子类可见 public int d 4; // 全局可见 private void privateMethod() {} protected void protectedMethod() {} } // 文件pkg2/Sub.java package pkg2; import pkg1.Base; public class Sub extends Base { public void test() { // System.out.println(a); // 编译错误private 不可见 // System.out.println(b); // 编译错误default 跨包不可见 System.out.println(c); // 可以protected 对子类可见 System.out.println(d); // 可以public 全局可见 protectedMethod(); // 可以继承来的 protected 方法 } }这段代码把“封装”从口号变成了编译器的实际约束。private字段只能通过 getter/setter 访问这正是第 3 章编程题里 Student 类写getName/setName的原因protected的微妙之处在于它跨包时只对子类可见同包内则等同于 default很多人在写工具类时误用 protected 导致外部调不到。参数上没什么可调但要注意字段默认值int 为 0、引用为 null只在成员变量上成立局部变量不初始化直接用会编译报错这是第 2 章和第 3 章的交界知识点。4.2 构造方法、this 与 super 的调用链第 3 章简答题第 1、2 问反复强调构造方法“方法名与类名相同、无返回值声明、不能 return 值”。第 4 章编程题里UnderGraduate用super(name, age)调父类构造这条链的执行顺序是新手最容易搞混的。写个带打印的版本一眼看清顺序。class Person { String name; Person(String name) { this.name name; System.out.println(1. Person 构造执行, name name); } } class Student extends Person { int age; Student(String name, int age) { super(name); // 必须第一行否则编译报错 this.age age; System.out.println(2. Student 构造执行, age age); } } public class ConstructorOrder { public static void main(String[] args) { new Student(zhangsan, 20); // 输出顺序先 Person 后 Student } }super(...)必须是子类构造方法的第一条语句这是硬规则如果子类构造里不写编译器会自动插入super()去调父类无参构造而父类一旦只定义了有参构造、没写无参构造子类就会编译失败——这是继承体系里最常见的翻车点之一。this(...)用于同类构造方法之间互相调用同样必须在第一行且不能和super(...)同时出现。理解这条调用链后面看 Spring 里 Bean 的初始化顺序、看任何框架的继承结构都不会懵。4.3 抽象类与接口的选型第 4 章编程题给的答案第 4 章编程题第 2 问用Shape接口 Square/Circle实现类演示多态简答题第 3 问讲了抽象类和接口的区别。选型上我的经验是需要定义“是什么”且带共享状态/实现用抽象类需要定义“能做什么”的能力契约用接口。Java 8 之后接口可以有 default 方法和 static 方法边界模糊了一些但“单继承多实现”这条没变。interface Shape { double area(double v); // 抽象方法实现类必须写 default String desc() { // 默认方法实现类可不写 return 面积 area(1); } } abstract class AbstractShape implements Shape { protected String color red; // 抽象类可以有成员变量 public abstract double area(double v); public String getColor() { return color; } } class Square extends AbstractShape { public double area(double side) { return side * side; } } public class ShapeDemo { public static void main(String[] args) { Shape s new Square(); // 父类型引用指向子类对象 System.out.println(s.area(2)); System.out.println(s.desc()); } }这里体现的是第 4 章简答题第 2 问说的“父类类型变量引用子类对象根据被引用子类对象的特性得到不同运行效果”也就是运行期多态靠的是方法表在运行时动态绑定。和第 3 章的重载编译期静态分派对照着看两个概念就不会混。接口里不能有实例字段抽象类可以有接口方法默认 public抽象类方法可以任意访问修饰符——这些差异在写框架扩展点时直接决定你的设计能不能落地。5. 集合、IO 与 JDBC第 6 到 9 章的踩坑清单第 5 到 9 章跨度大但答案的组织方式很统一每章都是填空、判断、选择、简答、编程五段式。真正有复现价值的是编程题尤其是第 6 章 HashSet 去重、第 7 章字节流与字符流拷贝、第 9 章 JDBC 六步走。这三块恰好也是实际项目里 bug 最密集的地方。下面这份清单是我带人时反复遇到的按“现象 → 原因 → 解决”整理建议对照答案里的代码逐条验证。5.1 集合去重失效hashCode 与 equals 必须成对重写第 6 章编程题第 1 问用 HashSet 存 Person答案里重写了hashCode()返回name.hashCode()、equals()只比较 name。现象是明明两个 Person 的 name 相同HashSet 里却存了两条。原因在于 HashSet 先按 hashCode 定位桶再用 equals 比较只重写其中一个就会出现“hash 相同但 equals 判不等”或“equals 相等但 hash 不同落不同桶”的情况。import java.util.*; class Person { String name; int age; Person(String name, int age) { this.name name; this.age age; } Override public int hashCode() { return Objects.hash(name); } // 只按 name 算哈希 Override public boolean equals(Object o) { if (this o) return true; if (o null || getClass() ! o.getClass()) return false; Person p (Person) o; return Objects.equals(name, p.name); // 只按 name 判等 } } public class SetDedup { public static void main(String[] args) { SetPerson set new HashSet(); set.add(new Person(Jack, 25)); set.add(new Person(Jack, 27)); // name 相同被视为重复 System.out.println(set.size()); // 输出 1 } }解决方式就是成对重写且参与 equals 的字段必须参与 hashCode 计算。答案里用name.hashCode()是简化写法生产代码建议用Objects.hash(...)或 IDE 生成避免手写漏字段。另一个坑是可变对象放进 HashSet 后修改了参与哈希的字段导致再也查不到这条答案没提但很致命。5.2 IO 拷贝的编码与资源释放字节流和字符流别混用第 7 章编程题第 1 问同时给了字节流和字符流两种拷贝方式。现象是用字符流拷贝图片或压缩包文件损坏或者拷贝中文文本后乱码。原因是字符流底层依赖字符编码二进制文件经过解码再编码必然失真乱码则是FileReader用了平台默认编码源文件和运行环境编码不一致。import java.io.*; public class CopyDemo { // 二进制文件必须用字节流 public static void copyBinary(String src, String dest) throws IOException { try (InputStream in new FileInputStream(src); OutputStream out new FileOutputStream(dest)) { byte[] buf new byte[8192]; int len; while ((len in.read(buf)) ! -1) { out.write(buf, 0, len); } } } // 文本文件用字符流并显式指定编码 public static void copyText(String src, String dest) throws IOException { try (BufferedReader br new BufferedReader( new InputStreamReader(new FileInputStream(src), UTF-8)); BufferedWriter bw new BufferedWriter( new OutputStreamWriter(new FileOutputStream(dest), UTF-8))) { String line; while ((line br.readLine()) ! null) { bw.write(line); bw.newLine(); } } } }解决要点有三个二进制一律字节流文本才用字符流字符流务必显式指定编码别依赖平台默认用 try-with-resources 替代答案里手写的close()避免异常路径下资源泄漏。答案里in.close()写在正常流程末尾一旦read抛异常就关不掉这是教学代码和工程代码的典型差距。5.3 JDBC 六步走驱动、连接串与 PreparedStatement第 9 章简答题第 2 问把 JDBC 拆成加载驱动、获取连接、获取 Statement、执行 SQL、处理结果集、关闭连接六步编程题给了 insert/delete/update/select 的骨架。现象是ClassNotFoundException: com.mysql.jdbc.Driver或者 SQL 拼接导致注入。前者是驱动包没进 classpath后者是用了 Statement 拼字符串。import java.sql.*; public class JdbcDemo { private static final String URL jdbc:mysql://localhost:3306/javatest?useSSLfalseserverTimezoneUTC; private static final String USER root; private static final String PWD 1234; public static void main(String[] args) throws Exception { Class.forName(com.mysql.cj.jdbc.Driver); // 新版驱动类名带 cj try (Connection conn DriverManager.getConnection(URL, USER, PWD); PreparedStatement ps conn.prepareStatement( insert into tb_user(name, sex, email) values(?, ?, ?))) { ps.setString(1, zhangsan); ps.setString(2, 男); ps.setString(3, zexample.com); int rows ps.executeUpdate(); System.out.println(影响行数: rows); } } }参数说明useSSLfalse和serverTimezoneUTC是 MySQL 8 驱动常见的连接串参数缺了时区可能报The server time zone value is unrecognized驱动类名从com.mysql.jdbc.Driver变成com.mysql.cj.jdbc.Driver答案里用的是旧名跑不通时先查这里。用PreparedStatement而不是Statement拼串既预编译提性能又能防注入这正是简答题第 3 问强调的两点。连接、语句、结果集都要在 finally 或 try-with-resources 里关闭顺序与打开相反。6. 把答案变成自测脚本一套可复用的验证习惯答案类资源最大的风险是“看懂了但没跑过”所以我最后补一个进阶用法把每章编程题改造成带断言的迷你测试跑一遍就知道自己是不是真会了。不需要引入 JUnit用main方法加if断言就够重点是让“预期结果”显式写出来而不是靠肉眼比对控制台输出。public class SelfCheck { // 第 2 章1 到 100 的奇数和答案给的循环是 i 100注意边界 static int oddSum() { int sum 0; for (int i 1; i 100; i) { if (i % 2 ! 0) sum i; } return sum; } // 第 2 章冒泡排序验证结果有序 static int[] bubbleSort(int[] arr) { for (int i 0; i arr.length - 1; i) { for (int j 0; j arr.length - i - 1; j) { if (arr[j] arr[j 1]) { int t arr[j]; arr[j] arr[j 1]; arr[j 1] t; } } } return arr; } public static void main(String[] args) { // 断言 1奇数和。1~99 共 50 个奇数和为 2500 assertEq(2500, oddSum(), 奇数和); // 断言 2排序结果 int[] sorted bubbleSort(new int[]{25, 24, 12, 76, 101, 96, 28}); int[] expect {12, 24, 25, 28, 76, 96, 101}; for (int i 0; i expect.length; i) { assertEq(expect[i], sorted[i], 排序第 i 位); } System.out.println(全部通过); } static void assertEq(int expect, int actual, String tag) { if (expect ! actual) { throw new AssertionError(tag 期望 expect 实际 actual); } } }这段自测的价值在于暴露答案里的边界细节第 2 章奇数和用的是i 100所以 99 被算进去、100 不算结果 2500如果改成i 100结果不变100 是偶数但改成i 99就少加 99差 99。冒泡排序的内层边界arr.length - i - 1少减一次就会数组越界这是手写排序最常见的错。把这些断言跑通比对着答案点头有用得多。验证项对应章节预期结果常见错误奇数和第 2 章2500循环边界写成或 99冒泡排序第 2 章升序数组内层边界少减 i 导致越界HashSet 去重第 6 章size1只重写 equals 不重写 hashCode文本拷贝编码第 7 章无乱码依赖平台默认编码JDBC 插入第 9 章影响行数1驱动类名或时区参数缺失从那以后我每次拿到这类课后答案都强制自己先把编程题改写成带断言的版本再往下看因为“能跑通”和“知道为什么能跑通”之间隔着的就是这些边界值。希望这份拆解帮到你把答案用成规格书而不是用成背诵材料。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询