开篇一个月度巡检数据汇总报表程序系列最后一章把前面九章攒下的边角料一次收齐第九章结尾留了个悬念——为什么ArrayListint编译报错第二章欠了笔账——Math.round()怎么用还有字符串里的数字怎么变成真数字今天是几号、数据属于哪个月这类天天见的需求。全部塞进一个汇总报表程序里import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; public class ReportApp { public static void main(String[] args) { // 1. 包装类集合里装数字的唯一办法 // 从系统各处收集来的巡检次数模拟从不同接口拿到的字符串 String[] raw {128, 96, abc, 150, 105}; ArrayListInteger counts new ArrayList(); // 注意是 Integer 不是 int for (String s : raw) { try { counts.add(Integer.parseInt(s)); // 字符串 → int } catch (NumberFormatException e) { System.out.println(跳过脏数据 s); } } // 2. 汇总统计 int total 0; int max counts.get(0); for (Integer c : counts) { total c; // Integer 自动拆箱成 int 参与运算 if (c max) { max c; } } double avg (double) total / counts.size(); long avgRounded Math.round(avg); // 四舍五入成整数 // 3. 报表抬头日期时间 LocalDate today LocalDate.now(); LocalDate firstDay today.withDayOfMonth(1); // 本月 1 号 LocalDateTime now LocalDateTime.now(); DateTimeFormatter fmt DateTimeFormatter.ofPattern(yyyy年MM月dd日 HH:mm); String stamp now.format(fmt); // 4. 用 StringBuilder 拼报表 StringBuilder report new StringBuilder(); report.append( 月度巡检汇总报表 \n); report.append(统计区间).append(firstDay).append( ~ ).append(today).append(\n); report.append(生成时间).append(stamp).append(\n); report.append(有效数据).append(counts.size()).append( 条\n); report.append(巡检总数).append(total).append( 次\n); report.append(单周最高).append(max).append( 次\n); report.append(周均巡检).append(avgRounded).append( 次\n); System.out.print(report.toString()); } }输出跳过脏数据abc 月度巡检汇总报表 统计区间2026-08-01 ~ 2026-08-10 生成时间2026年08月10日 09:30 有效数据4 条 巡检总数479 次 单周最高150 次 周均巡检120 次程序不长但把本章四大主角都用上了包装类Integer、字符串转数字、Math、日期时间外加 StringBuilder 的实战复盘。逐个讲。第一部分包装类——基本类型的对象马甲为什么需要它第九章那个报错的根源ArrayListint编译不过。原因是泛型的尖括号里只能放引用类型而 int 是基本类型不是对象。Java 的解决办法给八种基本类型各配一个对象马甲这就是包装类基本类型包装类intIntegerlongLongdoubleDoublebooleanBooleancharCharacterbyte / short / floatByte / Short / Float基本类型小写、包装类首字母大写。八个里高频的只有 Integer 和 Double其余见到认识即可注意 char 的马甲是 Character不是 Char。所以集合里装数字的正确写法是ArrayListInteger counts new ArrayList();自动装箱与拆箱——不用你操心的转换counts.add(Integer.parseInt(s)); // add 需要 IntegerparseInt 返回 int total c; // c 是 Integer却能直接做加法这两行看着类型不匹配却能跑——因为 Java 自动做转换装箱基本类型 → 包装对象自动发生int 塞进 ArrayListInteger 时拆箱包装对象 → 基本类型自动发生Integer 参与加减乘除时。日常开发你几乎感觉不到它的存在这正是它设计的目的。但有一个必须知道的坑Integer a null; int b a; // NullPointerException拆箱拆了个空包装类是引用类型可以为 null拆箱一个 null 直接空指针。这个坑常见于从 HashMap 里 get 数字、数据库查出来的可空字段。教训一句话包装类参与运算前确保它不是 null。顺带对比一个考点Integer x 127; Integer y 127;则x y为 true但换成 128 就是 falseInteger 对 -128~127 有缓存池。理解结论即可——包装类比大小和 String 一样老老实实用 equals 或拆箱后比别用 。字符串与数字互转——天天用的两个小方法int n Integer.parseInt(128); // 字符串 → int脏数据会抛 NumberFormatException double d Double.parseDouble(18.5); // 字符串 → double String s String.valueOf(479); // 数字 → 字符串也可以 479parseInt是解析外部输入配置文件、前端传参、CSV的必经之路配第八章的 try-catch 食用就是本章案例里跳过脏数据的写法。第二部分Math——数学计算工具箱Math类全是静态方法Math.方法名(...)直接调。高频的就四个方法作用例子Math.round(x)四舍五入Math.round(119.75)→ 120Math.max(a, b)/Math.min(a, b)取大/取小Math.max(3, 5)→ 5Math.abs(x)绝对值Math.abs(-9)→ 9Math.pow(a, b)a 的 b 次方Math.pow(2, 10)→ 1024.0第二章埋的伏笔现在兑现(int) 9.99是截断得 9要四舍五入用Math.round(9.99)得 10。两个词记准截断用强转取整用 round。Math.random()生成 0.0~1.0 随机小数也存在但正经项目里随机数多用Random类使用频率一般知道即可不展开。第三部分日期时间——就用 java.timeJava 的日期 API 历史上很混乱老旧的Date、Calendar声名狼藉。现代 Java8 之后的正解只有一个java.time包。日常记三个类类装什么例子LocalDate只有日期2026-08-10LocalTime只有时间09:30:00LocalDateTime日期 时间2026-08-10T09:30高频操作一网打尽// 获取当前 LocalDate today LocalDate.now(); LocalDateTime now LocalDateTime.now(); // 指定日期 LocalDate d LocalDate.of(2026, 8, 10); // 取字段 int month today.getMonthValue(); // 8 int day today.getDayOfMonth(); // 10 // 加减运算返回新对象原对象不变——和 String 一样不可变 LocalDate tomorrow today.plusDays(1); LocalDate lastWeek today.minusWeeks(1); // 比较 boolean before d.isBefore(today); // 格式化输出DateTimeFormatter DateTimeFormatter fmt DateTimeFormatter.ofPattern(yyyy年MM月dd日 HH:mm); String text now.format(fmt); // 2026年08月10日 09:30 // 字符串解析回日期 LocalDate parsed LocalDate.parse(2026-08-10); // 默认认 ISO 格式两个注意plus/minus 返回新对象要接回来today today.plusDays(1)光调用不接收等于白调和 String 的 trim 一个道理格式串里的大小写有意义yyyy年、MM月大写、dd日、HH24 小时制、mm分钟小写。MM 和 mm 写反是经典笔误——月份变分钟数据全乱。老的Date/Calendar在维护旧项目时会遇到认识即可新代码一律 java.time。第四部分StringBuilder 复盘——一句话记住用法第四章讲过、本章案例又用了一次最后定型成肌肉记忆StringBuilder sb new StringBuilder(); sb.append(任意类型).append(123).append(\n); String result sb.toString();循环里拼字符串用 StringBuilder一次性简单拼接用。报表、日志、SQL 片段这类攒出来的长文本全是 StringBuilder 的主场。常踩的坑排雷清单ArrayListint编译报错泛型只能用包装类ArrayListInteger。包装类拆箱拆到 nullHashMap get 数字、可空字段转 int 前的经典空指针来源先判 null。包装类用 比较缓存池的存在让结果时真时假和 String 一样用 equals 或拆箱比。(int)当四舍五入是截断取整用Math.round()。日期加减不接收返回值today.plusDays(1)不改变 today必须接回。格式串 MM/mm 写反月大写和分钟小写写反不报错但结果全错。新代码还在用 Date/Calendar新项目请直接 java.time。本章小结也是全系列的收官包装类基本类型的对象马甲泛型和集合的入场券自动装箱拆箱无感工作但 null 拆箱会炸。Integer.parseInt/String.valueOf字符串与数字互转的标配。Mathround四舍五入、max/min、abs四个高频。日期时间LocalDate/LocalDateTimeDateTimeFormatter不可变、要接返回值MM/mm 别写反。StringBuilder攒长文本的唯一姿势。系列回顾十章走完你手里有什么回看这十章一条线走下来程序骨架——main 方法五要素代码不许游离于类类型两阵营——八种基本类型 vs 引用类型与 equals 的分水岭流程控制——if 管范围、switch 管等值、循环三兄弟数组与字符串——定长容器与高频方法StringBuilder 初登场类与对象——字段方法构造器this 与 static 的分界封装与重载——private getter/setter 的 Java 式规矩继承与多态——是一个用继承能做什么用接口异常处理——程序经得起真实环境的折腾集合——ArrayList、HashMap、HashSet日常开发的 80%工具类——包装类、Math、日期时间补齐最后一块拼图。这套语法足够你看懂主流 Java 业务代码、写结构清晰的小程序、从容应对软考下午题的 Java 填空。再往前的路——Spring 框架、数据库、并发——都属于应用与深水区需要时另开系列。学语言没有捷径但有条近路把每一章的案例亲手敲一遍再改一改——把巡检换成你自己的业务把设备换成你熟悉的对象。语法在指尖过一遍才算真的归你。