从 Java 零基础到能写小游戏这30天我踩过的坑和翻过的山。 你好我是 Evan一名计算机专业的学长也是《大一突围》专栏的作者。大一下学期我给自己定了一个目标连续30天每天至少写30分钟 Java 代码。为什么要定这个目标因为之前我总是“三天打鱼两天晒网”书看了半本视频收藏了几十个但一写代码就卡壳。这30天我把自己当成小白鼠记录下每天的真实状态、遇到的问题、怎么解决的以及最重要的——我到底改变了什么。今天分享给你希望能给你一些启发和勇气。欢迎来到《大一突围》专栏。一、30天概览一个普通 Java 初学者的进化轨迹二、第一周从“Hello World”到怀疑人生Day 1-2环境搭建 第一个程序任务安装 JDK IntelliJ IDEA写HelloWorld.java。遇到的问题命令行找不到javac环境变量没配好。解决方法搜索“Java 环境变量配置”跟着步骤把JAVA_HOME和Path配好。收获学会了在 Stack Overflow 上搜错误信息。Day 3-4变量和数据类型任务练习 int、double、boolean、String 的声明和运算。遇到的问题混淆和写if (a 5)导致编译错误。解决方法把“赋值”和“相等比较”贴在显示器边上。收获养成了写一行空一行的习惯代码更清晰。Day 5-7循环和数组任务用 for 循环输出 1-100 的素数用数组存储成绩并求平均分。遇到的问题数组越界ArrayIndexOutOfBoundsException循环条件写错导致死循环。解决方法打印索引值观察边界用i arr.length而不是i arr.length。收获理解了“边界敏感”学会了用System.out.println辅助调试。第7天小结感觉语法能看懂但自己写一个完整的程序还是磕磕绊绊。最大的困难是“手跟不上脑”。 第一周完整Demo输出素数 数组求平均public class Week1Demo { public static void main(String[] args) { // 1. 输出1-100之间的素数 System.out.println(1-100之间的素数); for (int num 2; num 100; num) { boolean isPrime true; for (int i 2; i Math.sqrt(num); i) { if (num % i 0) { isPrime false; break; } } if (isPrime) { System.out.print(num ); } } System.out.println(); // 2. 数组存储成绩并求平均分 int[] scores {85, 92, 78, 90, 88}; int sum 0; for (int i 0; i scores.length; i) { sum scores[i]; } double average (double) sum / scores.length; System.out.println(平均分 average); } }三、第二周开始写方法接触调试器Day 8-10定义和调用方法任务写一个方法int max(int a, int b)再写一个方法boolean isPrime(int n)。遇到的问题忘了写return或者返回类型写错方法调用时参数顺序传反。解决方法写方法前先写注释说明“输入什么返回什么”用 JUnit 写简单测试。收获学会了模块化思维不再把所有代码塞在main里。Day 11-12学会用 IDEA 断点调试任务写一个递归计算阶乘的方法并观察栈的变化。遇到的问题递归没有终止条件导致StackOverflowError。解决方法用断点单步执行观察变量n的变化发现忘记写if (n 1) return 1;。收获调试器是最伟大的老师。从此不再害怕报错而是兴奋地打断点追踪。Day 13-14练习数组算法冒泡排序、二分查找任务手写冒泡排序再用二分查找找指定元素。遇到的问题冒泡排序内层循环边界写错排序结果不对二分查找死循环。解决方法用纸笔画数组的变化过程然后对照代码。收获画图 打印中间状态 解决 90% 的逻辑错误。第14天小结开始有“手感”了写循环和数组不再那么害怕。能够独立解决简单的编译错误。 第二周完整Demo方法 冒泡排序 二分查找public class Week2Demo { // 方法示例求最大值 public static int max(int a, int b) { return a b ? a : b; } // 冒泡排序升序 public static void bubbleSort(int[] arr) { for (int i 0; i arr.length - 1; i) { for (int j 0; j arr.length - 1 - i; j) { if (arr[j] arr[j 1]) { int temp arr[j]; arr[j] arr[j 1]; arr[j 1] temp; } } } } // 二分查找前提数组已排序 public static int binarySearch(int[] arr, int target) { int left 0, right arr.length - 1; while (left right) { int mid left (right - left) / 2; if (arr[mid] target) return mid; else if (arr[mid] target) left mid 1; else right mid - 1; } return -1; } public static void main(String[] args) { // 测试max方法 System.out.println(max(10, 20) max(10, 20)); // 冒泡排序 int[] arr {64, 34, 25, 12, 22, 11, 90}; bubbleSort(arr); System.out.print(排序后的数组); for (int num : arr) System.out.print(num ); System.out.println(); // 二分查找 int index binarySearch(arr, 22); System.out.println(22 的索引位置 index); } }四、第三周面向对象 —— 痛苦的转折点Day 15-17类与对象、构造方法任务定义一个Student类属性学号、姓名、成绩创建对象并打印。遇到的问题忘记new导致NullPointerException。构造方法名写错写成student而不是Student。直接访问私有属性还没学封装。解决方法逐个查编译错误用this区分成员变量和参数。收获理解了“类是一张图纸对象是盖好的房子”。Day 18-20封装、getter/setter、this任务把Student的属性设为private提供getName()和setName()等方法并在setScore中加入校验0-100。遇到的问题在setScore中忘记校验传入负数也能改getter 返回了内部引用返回数组时导致外部可修改。解决方法添加if (score 0 || score 100) throw new IllegalArgumentException(...)返回数组时用return Arrays.copyOf(...)。收获理解了封装的意义——“保护数据不被随意破坏”。Day 21继承和多态初体验任务定义Person父类和Student子类重写toString()。遇到的问题子类构造方法忘记super()调用父类构造重写时注解Override写错方法名导致不是重载。解决方法使用 IDE 的自动生成功能Generate → Constructor / Override Methods。收获代码复用真的很香但也容易出错需要谨慎。第21天小结面向对象是道坎跨过去之后代码的世界变得有结构了。开始理解“万物皆对象”。 第三周完整Demo学生类封装 继承示例// 父类 Person class Person { protected String name; public Person(String name) { this.name name; } public void sayHello() { System.out.println(你好我是 name); } } // 子类 Student继承 Person class Student extends Person { private String stuId; private int score; // 构造方法 public Student(String name, String stuId, int score) { super(name); // 调用父类构造 this.stuId stuId; setScore(score); // 使用setter进行校验 } // 封装getter / setter public String getStuId() { return stuId; } public int getScore() { return score; } public void setScore(int score) { if (score 0 || score 100) { throw new IllegalArgumentException(成绩必须在0-100之间); } this.score score; } Override public void sayHello() { System.out.println(大家好我是学生 name 学号 stuId 成绩 score); } } // 测试类 public class Week3Demo { public static void main(String[] args) { Student s new Student(张三, 2024001, 88); s.sayHello(); // 多态调用重写后的方法 System.out.println(学号 s.getStuId()); System.out.println(成绩 s.getScore()); } }五、第四周第一个小项目 综合总结Day 22-25命令行学生管理系统CRUD任务用 ArrayList 存储学生实现增删改查、计算平均分、按成绩排序。遇到的问题删除时用for循环 remove导致跳删索引问题。比较字符串用而不是equals。输入整数时用户输字母导致InputMismatchException。解决方法删除用迭代器或倒序遍历。字符串比较一律用.equals()。用try-catch捕获异常并提示重新输入。收获第一次独立完成 200 行以上的项目虽然代码很“土”但能跑通。Day 26-28代码重构 学习集合框架任务把学生管理系统的重复代码提取成方法改用HashMap实现按学号快速查找。遇到的问题重构后某个功能不工作了因为改了一个方法没改调用处。解决方法写单元测试用main方法简单测试改一处测一处。收获重构是真功夫要配合测试。Day 29-30整理笔记写这篇博客回顾30天的代码GitHub 仓库统计了一下共写了约 2500 行 Java 代码包括重复练习。遇到并解决了 40 个不同类型的错误。形成了每天写代码的习惯不再害怕空白编辑器。 第四周完整Demo学生管理系统核心功能import java.util.*; class StudentRecord { private String id; private String name; private int score; public StudentRecord(String id, String name, int score) { this.id id; this.name name; setScore(score); } // getters and setters (省略实际代码应包含) public String getId() { return id; } public String getName() { return name; } public int getScore() { return score; } public void setScore(int score) { if (score 0 || score 100) throw new IllegalArgumentException(成绩范围错误); this.score score; } Override public String toString() { return id | name | score; } } public class Week4Demo { private static ListStudentRecord list new ArrayList(); private static Scanner sc new Scanner(System.in); // 添加学生 public static void addStudent() { System.out.print(学号); String id sc.next(); System.out.print(姓名); String name sc.next(); System.out.print(成绩); int score sc.nextInt(); list.add(new StudentRecord(id, name, score)); System.out.println(添加成功); } // 按学号删除 public static void deleteStudent() { System.out.print(输入要删除的学号); String id sc.next(); boolean removed list.removeIf(s - s.getId().equals(id)); System.out.println(removed ? 删除成功 : 未找到该学号); } // 查询所有学生 public static void listAll() { if (list.isEmpty()) System.out.println(暂无学生); else list.forEach(System.out::println); } // 计算平均分 public static void averageScore() { if (list.isEmpty()) { System.out.println(暂无学生); return; } double avg list.stream().mapToInt(StudentRecord::getScore).average().orElse(0); System.out.println(平均分 avg); } public static void main(String[] args) { while (true) { System.out.println(\n1.添加 2.删除 3.列表 4.平均分 5.退出); int choice sc.nextInt(); switch (choice) { case 1 - addStudent(); case 2 - deleteStudent(); case 3 - listAll(); case 4 - averageScore(); case 5 - { System.out.println(再见); return; } } } } }六、这30天我究竟改变了什么1. 技术上的改变从语法恐惧→ 能熟练使用变量、循环、数组、方法、类、异常处理。从只会复制粘贴→ 能参考文档写出自己的代码。从遇到 bug 就放弃→ 能冷静读异常栈、打断点、搜索解决方案。2. 习惯上的改变每天固定时间写代码晚上 8:00-8:30形成肌肉记忆。使用 Git 每天提交能看到自己的进步轨迹。写代码前先想思路写注释而不是直接敲。3. 心态上的改变从“我不会”到“我试试”遇到新任务第一反应不再是退缩。接受不完美允许自己写出“烂代码”后续再优化。享受解决问题的快感debug 成功后的成就感比打游戏更持久。七、给也想挑战30天的你避坑指南八、资源推荐Java 初学者在线练习CodeGym、LeetCode简单题、Codewars8kyu。视频课程B站“遇见狂神说”Java基础、尚硅谷宋红康。书籍《Head First Java》、《Java核心技术 卷I》。工具IntelliJ IDEA社区版、Git、GitHub。❓ 问题你有没有试过连续写代码的计划坚持了多久或者你正准备开始这样的挑战欢迎在评论区分享你的经历或立下flag30天后回来看看。我会选出 3 位同学送出《Java 常见错误排查清单》和《30天打卡表模板》。如果本文给了你开始30天挑战的勇气请点 赞 关注本专栏《大一突围》持续输出编程成长干货。收藏本文等你完成30天挑战后回来分享你的改变