Week 1-8: Spring Boot 学习计划完整项目
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
258
week1/addressbook/AddressBookApp.java
Normal file
258
week1/addressbook/AddressBookApp.java
Normal file
@@ -0,0 +1,258 @@
|
||||
package addressbook;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 第 7 天综合项目 —— 命令行通讯录
|
||||
*
|
||||
* 综合运用本周所学:
|
||||
* 1. 类与对象(Contact 内部类)
|
||||
* 2. 封装(private 属性 + getter/setter)
|
||||
* 3. 集合框架(HashMap 存储,ArrayList 排序)
|
||||
* 4. 流程控制(while 菜单循环 + switch 分支)
|
||||
* 5. 异常处理(try-catch)
|
||||
* 6. 方法封装(每个功能一个方法)
|
||||
*/
|
||||
public class AddressBookApp {
|
||||
|
||||
private static final Scanner scanner = new Scanner(System.in);
|
||||
// 核心数据结构:以姓名为 key,Contact 对象为 value
|
||||
private static final Map<String, Contact> contacts = new LinkedHashMap<>();
|
||||
// LinkedHashMap 保持插入顺序,方便"查看全部"时有序展示
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("============================================");
|
||||
System.out.println(" 📒 命令行通讯录 v1.0");
|
||||
System.out.println(" 你的第一个 Java 项目!");
|
||||
System.out.println("============================================");
|
||||
|
||||
// 预置几条测试数据,方便快速体验
|
||||
initSampleData();
|
||||
|
||||
// 主循环
|
||||
while (true) {
|
||||
printMenu();
|
||||
int choice = readChoice();
|
||||
if (!executeChoice(choice)) {
|
||||
break; // 用户选择退出
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 菜单 ====================
|
||||
|
||||
static void printMenu() {
|
||||
System.out.println("\n-----------------------------------------");
|
||||
System.out.println(" 1. 添加联系人");
|
||||
System.out.println(" 2. 查看全部联系人");
|
||||
System.out.println(" 3. 搜索联系人");
|
||||
System.out.println(" 4. 修改联系人");
|
||||
System.out.println(" 5. 删除联系人");
|
||||
System.out.println(" 6. 退出");
|
||||
System.out.println("-----------------------------------------");
|
||||
System.out.print("请输入你的选择 (1-6): ");
|
||||
}
|
||||
|
||||
static int readChoice() {
|
||||
try {
|
||||
return scanner.nextInt();
|
||||
} catch (InputMismatchException e) {
|
||||
scanner.nextLine(); // 清掉无效输入
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/** @return false 表示用户选择了退出 */
|
||||
static boolean executeChoice(int choice) {
|
||||
scanner.nextLine(); // 清除换行符(nextInt 不会消耗换行符)
|
||||
|
||||
switch (choice) {
|
||||
case 1 -> addContact();
|
||||
case 2 -> listContacts();
|
||||
case 3 -> searchContact();
|
||||
case 4 -> updateContact();
|
||||
case 5 -> deleteContact();
|
||||
case 6 -> {
|
||||
System.out.println("\n再见!👋");
|
||||
scanner.close();
|
||||
return false;
|
||||
}
|
||||
default -> System.out.println("⚠ 无效选项,请输入 1-6。");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ==================== CRUD 操作 ====================
|
||||
|
||||
/** 1. 添加联系人 */
|
||||
static void addContact() {
|
||||
System.out.println("\n--- 添加联系人 ---");
|
||||
|
||||
String name = readInput("姓名: ");
|
||||
// 校验:姓名不能为空
|
||||
if (name.trim().isEmpty()) {
|
||||
System.out.println("⚠ 姓名不能为空!");
|
||||
return;
|
||||
}
|
||||
// 校验:不允许重名(HashMap 的 key 唯一)
|
||||
if (contacts.containsKey(name)) {
|
||||
System.out.println("⚠ 联系人 [" + name + "] 已存在!如需修改请选择功能 4。");
|
||||
return;
|
||||
}
|
||||
|
||||
String phone = readInput("电话: ");
|
||||
String email = readInput("邮箱: ");
|
||||
String address = readInput("地址: ");
|
||||
|
||||
Contact c = new Contact(name, phone, email, address);
|
||||
contacts.put(name, c);
|
||||
System.out.println("✅ 联系人 [" + name + "] 已添加!");
|
||||
}
|
||||
|
||||
/** 2. 查看全部联系人 */
|
||||
static void listContacts() {
|
||||
System.out.println("\n--- 全部联系人 ---");
|
||||
|
||||
if (contacts.isEmpty()) {
|
||||
System.out.println("通讯录为空,快去添加第一个联系人吧!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 打印表头
|
||||
System.out.printf("%-4s %-12s %-16s %-20s %-20s\n", "序号", "姓名", "电话", "邮箱", "地址");
|
||||
System.out.println("---- ------------ ---------------- -------------------- --------------------");
|
||||
|
||||
int index = 1;
|
||||
for (Contact c : contacts.values()) {
|
||||
System.out.printf("%-4d %-12s %-16s %-20s %-20s\n",
|
||||
index++, c.name, c.phone, c.email, c.address);
|
||||
}
|
||||
System.out.println("\n共 " + contacts.size() + " 个联系人。");
|
||||
}
|
||||
|
||||
/** 3. 搜索联系人(支持姓名精确搜索,以及姓名/电话的模糊搜索) */
|
||||
static void searchContact() {
|
||||
System.out.println("\n--- 搜索联系人 ---");
|
||||
String keyword = readInput("请输入搜索关键词(支持姓名或电话的模糊匹配): ").trim();
|
||||
|
||||
if (keyword.isEmpty()) {
|
||||
System.out.println("⚠ 搜索关键词不能为空!");
|
||||
return;
|
||||
}
|
||||
|
||||
List<Contact> results = new ArrayList<>();
|
||||
for (Contact c : contacts.values()) {
|
||||
if (c.name.contains(keyword) || c.phone.contains(keyword)) {
|
||||
results.add(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (results.isEmpty()) {
|
||||
System.out.println("未找到匹配的联系人。");
|
||||
} else {
|
||||
System.out.println("\n找到 " + results.size() + " 条记录:");
|
||||
for (Contact c : results) {
|
||||
System.out.println(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 4. 修改联系人 */
|
||||
static void updateContact() {
|
||||
System.out.println("\n--- 修改联系人 ---");
|
||||
String name = readInput("请输入要修改的联系人姓名: ").trim();
|
||||
|
||||
Contact target = contacts.get(name);
|
||||
if (target == null) {
|
||||
System.out.println("⚠ 未找到联系人 [" + name + "]。");
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("当前信息:" + target);
|
||||
System.out.println("(直接回车保留原值,输入新值则更新)");
|
||||
|
||||
String newPhone = readInput("新电话 [" + target.phone + "]: ");
|
||||
if (!newPhone.trim().isEmpty()) {
|
||||
target.setPhone(newPhone);
|
||||
}
|
||||
|
||||
String newEmail = readInput("新邮箱 [" + target.email + "]: ");
|
||||
if (!newEmail.trim().isEmpty()) {
|
||||
target.setEmail(newEmail);
|
||||
}
|
||||
|
||||
String newAddress = readInput("新地址 [" + target.address + "]: ");
|
||||
if (!newAddress.trim().isEmpty()) {
|
||||
target.setAddress(newAddress);
|
||||
}
|
||||
|
||||
System.out.println("✅ 联系人 [" + name + "] 已更新!");
|
||||
}
|
||||
|
||||
/** 5. 删除联系人 */
|
||||
static void deleteContact() {
|
||||
System.out.println("\n--- 删除联系人 ---");
|
||||
String name = readInput("请输入要删除的联系人姓名: ").trim();
|
||||
|
||||
if (!contacts.containsKey(name)) {
|
||||
System.out.println("⚠ 未找到联系人 [" + name + "]。");
|
||||
return;
|
||||
}
|
||||
|
||||
// 二次确认
|
||||
System.out.print("确认删除 [" + name + "]?(y/n): ");
|
||||
String confirm = scanner.nextLine().trim().toLowerCase();
|
||||
|
||||
if ("y".equals(confirm) || "yes".equals(confirm)) {
|
||||
contacts.remove(name);
|
||||
System.out.println("✅ 联系人 [" + name + "] 已删除!");
|
||||
} else {
|
||||
System.out.println("已取消删除。");
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 工具方法 ====================
|
||||
|
||||
/** 打印提示并读取一行输入 */
|
||||
static String readInput(String prompt) {
|
||||
System.out.print(prompt);
|
||||
return scanner.nextLine();
|
||||
}
|
||||
|
||||
/** 预置示例数据 */
|
||||
static void initSampleData() {
|
||||
contacts.put("张三", new Contact("张三", "13800138001", "zhangsan@mail.com", "北京市朝阳区"));
|
||||
contacts.put("李四", new Contact("李四", "13900139002", "lisi@mail.com", "上海市浦东新区"));
|
||||
contacts.put("王五", new Contact("王五", "13700137003", "wangwu@mail.com", "广州市天河区"));
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== Contact 实体类 ====================
|
||||
|
||||
class Contact {
|
||||
String name;
|
||||
String phone;
|
||||
String email;
|
||||
String address;
|
||||
|
||||
public Contact(String name, String phone, String email, String address) {
|
||||
this.name = name;
|
||||
this.phone = phone;
|
||||
this.email = email;
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
// Getter / Setter(体现封装)
|
||||
public String getName() { return name; }
|
||||
public String getPhone() { return phone; }
|
||||
public void setPhone(String phone) { this.phone = phone; }
|
||||
public String getEmail() { return email; }
|
||||
public void setEmail(String email) { this.email = email; }
|
||||
public String getAddress() { return address; }
|
||||
public void setAddress(String address) { this.address = address; }
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("[%s] 电话:%s 邮箱:%s 地址:%s", name, phone, email, address);
|
||||
}
|
||||
}
|
||||
36
week1/day01/HelloWorld.java
Normal file
36
week1/day01/HelloWorld.java
Normal file
@@ -0,0 +1,36 @@
|
||||
package day01;
|
||||
|
||||
/**
|
||||
* 第 1 天:Hello World
|
||||
* 目标:理解 Java 程序的基本结构和运行方式
|
||||
*
|
||||
* 概念速查:
|
||||
* public class —— 声明一个公共类,类名必须和文件名一致
|
||||
* public static void main(String[] args) —— 程序的入口方法
|
||||
* System.out.println() —— 向控制台输出一行文字
|
||||
*
|
||||
* 运行方式:
|
||||
* javac HelloWorld.java (编译生成 HelloWorld.class)
|
||||
* java HelloWorld (运行)
|
||||
*/
|
||||
public class HelloWorld {
|
||||
public static void main(String[] args) {
|
||||
// 1. 最简单的输出
|
||||
System.out.println("Hello, Java!");
|
||||
|
||||
// 2. 加点花样:用转义字符
|
||||
System.out.println("-------------------");
|
||||
System.out.println("欢迎来到 Java 世界!");
|
||||
System.out.println("-------------------");
|
||||
|
||||
// 3. print vs println(print 不换行)
|
||||
System.out.print("Java ");
|
||||
System.out.print("一次编译,");
|
||||
System.out.println("到处运行。");
|
||||
|
||||
// 4. 转义字符
|
||||
System.out.println("第一行\n第二行"); // \n 换行
|
||||
System.out.println("姓名\t年龄\t成绩"); // \t 制表符
|
||||
System.out.println("他说:\"你好\""); // \" 双引号
|
||||
}
|
||||
}
|
||||
78
week1/day02/Calculator.java
Normal file
78
week1/day02/Calculator.java
Normal file
@@ -0,0 +1,78 @@
|
||||
package day02;
|
||||
|
||||
/**
|
||||
* 第 2 天:计算器 —— 变量、数据类型、运算符
|
||||
* 目标:掌握 Java 基本数据类型和运算符
|
||||
*
|
||||
* 概念速查:
|
||||
* int —— 整数(4 字节,约 ±21 亿)
|
||||
* double —— 浮点数(8 字节,双精度)
|
||||
* Scanner —— 从控制台读取用户输入
|
||||
* + - * / % —— 加减乘除取余
|
||||
*/
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Calculator {
|
||||
public static void main(String[] args) {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
|
||||
System.out.println("========== 简易计算器 ==========");
|
||||
|
||||
// 读取第一个数
|
||||
System.out.print("请输入第一个数字: ");
|
||||
double num1 = scanner.nextDouble();
|
||||
|
||||
// 读取运算符
|
||||
System.out.print("请输入运算符 (+, -, *, /): ");
|
||||
// 注意:next() 读取字符串,charAt(0) 取第一个字符
|
||||
char operator = scanner.next().charAt(0);
|
||||
|
||||
// 读取第二个数
|
||||
System.out.print("请输入第二个数字: ");
|
||||
double num2 = scanner.nextDouble();
|
||||
|
||||
double result = 0;
|
||||
boolean valid = true; // 标记运算是否合法
|
||||
|
||||
// 根据运算符执行不同运算
|
||||
switch (operator) {
|
||||
case '+':
|
||||
result = num1 + num2;
|
||||
break;
|
||||
case '-':
|
||||
result = num1 - num2;
|
||||
break;
|
||||
case '*':
|
||||
result = num1 * num2;
|
||||
break;
|
||||
case '/':
|
||||
// 除法需要特殊处理:除数不能为 0
|
||||
if (num2 != 0) {
|
||||
result = num1 / num2;
|
||||
} else {
|
||||
System.out.println("错误:除数不能为零!");
|
||||
valid = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
System.out.println("错误:不支持的运算符!");
|
||||
valid = false;
|
||||
}
|
||||
|
||||
// 输出结果
|
||||
if (valid) {
|
||||
System.out.println("----------------------------");
|
||||
System.out.printf("%.2f %c %.2f = %.2f\n", num1, operator, num2, result);
|
||||
}
|
||||
|
||||
// 额外练习:类型转换演示
|
||||
System.out.println("\n--- 类型转换小实验 ---");
|
||||
int a = 10;
|
||||
int b = 3;
|
||||
System.out.println("整数除法 10 / 3 = " + (a / b)); // 输出 3(截断)
|
||||
System.out.println("浮点除法 10.0 / 3 = " + (10.0 / b)); // 输出 3.333...
|
||||
System.out.println("取余 10 % 3 = " + (a % b)); // 输出 1
|
||||
|
||||
scanner.close();
|
||||
}
|
||||
}
|
||||
63
week1/day03/GuessNumber.java
Normal file
63
week1/day03/GuessNumber.java
Normal file
@@ -0,0 +1,63 @@
|
||||
package day03;
|
||||
|
||||
/**
|
||||
* 第 3 天:猜数字游戏 —— while 循环 + if 判断
|
||||
* 目标:掌握 while 循环和条件判断的配合使用
|
||||
*
|
||||
* 游戏规则:程序随机生成 1-100 的数字,玩家最多猜 7 次,
|
||||
* 每次猜测后提示"大了"或"小了",猜中或次数用完则结束。
|
||||
*/
|
||||
import java.util.Scanner;
|
||||
import java.util.Random;
|
||||
|
||||
public class GuessNumber {
|
||||
public static void main(String[] args) {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
Random random = new Random();
|
||||
|
||||
// 生成 1~100 的随机整数
|
||||
int target = random.nextInt(100) + 1;
|
||||
|
||||
int maxAttempts = 7; // 最多猜 7 次
|
||||
int attempts = 0; // 已猜次数
|
||||
boolean guessed = false;
|
||||
|
||||
System.out.println("========== 猜数字游戏 ==========");
|
||||
System.out.println("我已想好一个 1~100 之间的数字,你有 " + maxAttempts + " 次机会!");
|
||||
|
||||
// while 循环:当还有剩余次数且未猜中时继续
|
||||
while (attempts < maxAttempts && !guessed) {
|
||||
attempts++;
|
||||
System.out.print("\n第 " + attempts + " 次猜测,请输入数字: ");
|
||||
int guess = scanner.nextInt();
|
||||
|
||||
if (guess < 1 || guess > 100) {
|
||||
System.out.println("请输入 1~100 之间的数字!");
|
||||
attempts--; // 不浪费这次机会
|
||||
continue; // 跳过本次循环剩余代码
|
||||
}
|
||||
|
||||
if (guess == target) {
|
||||
System.out.println("\n🎉 恭喜你猜对了!答案就是 " + target + "!");
|
||||
System.out.println("你一共猜了 " + attempts + " 次。");
|
||||
guessed = true;
|
||||
} else if (guess > target) {
|
||||
System.out.println("太大了!");
|
||||
} else {
|
||||
System.out.println("太小了!");
|
||||
}
|
||||
|
||||
// 提示剩余次数
|
||||
if (!guessed && attempts < maxAttempts) {
|
||||
System.out.println("还有 " + (maxAttempts - attempts) + " 次机会。");
|
||||
}
|
||||
}
|
||||
|
||||
// 没猜中的情况
|
||||
if (!guessed) {
|
||||
System.out.println("\n😢 很遗憾,次数用完了!正确答案是 " + target + "。");
|
||||
}
|
||||
|
||||
scanner.close();
|
||||
}
|
||||
}
|
||||
47
week1/day03/MultiplicationTable.java
Normal file
47
week1/day03/MultiplicationTable.java
Normal file
@@ -0,0 +1,47 @@
|
||||
package day03;
|
||||
|
||||
/**
|
||||
* 第 3 天:九九乘法表 —— for 循环嵌套
|
||||
* 目标:理解 for 循环的执行顺序和嵌套逻辑
|
||||
*
|
||||
* 输出效果:
|
||||
* 1×1=1
|
||||
* 1×2=2 2×2=4
|
||||
* 1×3=3 2×3=6 3×3=9
|
||||
* ...
|
||||
* 1×9=9 2×9=18 3×9=27 ... 9×9=81
|
||||
*/
|
||||
public class MultiplicationTable {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("========== 九九乘法表 ==========\n");
|
||||
|
||||
// 外层循环控制行(被乘数 i 从 1 到 9)
|
||||
for (int i = 1; i <= 9; i++) {
|
||||
// 内层循环控制列(乘数 j 从 1 到 i,三角形输出)
|
||||
for (int j = 1; j <= i; j++) {
|
||||
// \t 制表符对齐 \t 制表符对齐
|
||||
System.out.print(j + "×" + i + "=" + (i * j) + "\t");
|
||||
}
|
||||
// 每行结束后换行
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
// 附加练习:完整矩形乘法表(1-9 × 1-9)
|
||||
System.out.println("\n========== 完整矩形乘法表 ==========\n");
|
||||
|
||||
// 先打表头
|
||||
System.out.print(" |");
|
||||
for (int i = 1; i <= 9; i++) {
|
||||
System.out.printf("%4d", i);
|
||||
}
|
||||
System.out.println("\n---+------------------------------------");
|
||||
|
||||
for (int i = 1; i <= 9; i++) {
|
||||
System.out.printf(" %d |", i);
|
||||
for (int j = 1; j <= 9; j++) {
|
||||
System.out.printf("%4d", i * j);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
}
|
||||
118
week1/day04/StudentScoreManager.java
Normal file
118
week1/day04/StudentScoreManager.java
Normal file
@@ -0,0 +1,118 @@
|
||||
package day04;
|
||||
|
||||
/**
|
||||
* 第 4 天:学生成绩管理器 —— 数组、ArrayList、方法
|
||||
* 目标:掌握数据组织(数组/动态数组)和代码组织(方法封装)
|
||||
*
|
||||
* 功能:添加成绩、查看全部、求平均分、找最高/最低分
|
||||
*/
|
||||
import java.util.ArrayList;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class StudentScoreManager {
|
||||
|
||||
// Scanner 作为静态成员,全局复用(记得最后 close)
|
||||
static Scanner scanner = new Scanner(System.in);
|
||||
// ArrayList<Integer> 动态存储成绩
|
||||
static ArrayList<Integer> scores = new ArrayList<>();
|
||||
|
||||
public static void main(String[] args) {
|
||||
while (true) {
|
||||
printMenu();
|
||||
System.out.print("请选择操作 (1-5): ");
|
||||
int choice = scanner.nextInt();
|
||||
|
||||
switch (choice) {
|
||||
case 1 -> addScore();
|
||||
case 2 -> showAllScores();
|
||||
case 3 -> showAverage();
|
||||
case 4 -> showMaxMin();
|
||||
case 5 -> {
|
||||
System.out.println("再见!");
|
||||
scanner.close();
|
||||
return; // 退出程序
|
||||
}
|
||||
default -> System.out.println("无效选项,请重试。");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 方法定义 ====================
|
||||
|
||||
/** 打印菜单 */
|
||||
static void printMenu() {
|
||||
System.out.println("\n========== 学生成绩管理器 ==========");
|
||||
System.out.println("1. 添加成绩");
|
||||
System.out.println("2. 查看全部成绩");
|
||||
System.out.println("3. 查看平均分");
|
||||
System.out.println("4. 查看最高分 / 最低分");
|
||||
System.out.println("5. 退出");
|
||||
System.out.println("====================================");
|
||||
}
|
||||
|
||||
/** 添加成绩 */
|
||||
static void addScore() {
|
||||
System.out.print("请输入成绩 (0-100): ");
|
||||
int score = scanner.nextInt();
|
||||
|
||||
// 基本输入校验
|
||||
if (score < 0 || score > 100) {
|
||||
System.out.println("成绩必须在 0-100 之间!");
|
||||
return;
|
||||
}
|
||||
|
||||
scores.add(score);
|
||||
System.out.println("✅ 第 " + scores.size() + " 个学生的成绩已添加: " + score);
|
||||
}
|
||||
|
||||
/** 查看全部成绩 */
|
||||
static void showAllScores() {
|
||||
if (scores.isEmpty()) {
|
||||
System.out.println("暂无成绩记录。");
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("\n--- 全部成绩 ---");
|
||||
// 传统 for 循环(需要索引)
|
||||
for (int i = 0; i < scores.size(); i++) {
|
||||
System.out.printf("学生 %d: %d 分\n", i + 1, scores.get(i));
|
||||
}
|
||||
System.out.println("共 " + scores.size() + " 名学生的成绩。");
|
||||
}
|
||||
|
||||
/** 求平均分 */
|
||||
static void showAverage() {
|
||||
if (scores.isEmpty()) {
|
||||
System.out.println("暂无成绩记录,无法计算平均分。");
|
||||
return;
|
||||
}
|
||||
|
||||
// 遍历求和
|
||||
int sum = 0;
|
||||
for (int s : scores) { // 增强 for 循环(foreach)
|
||||
sum += s;
|
||||
}
|
||||
double average = (double) sum / scores.size(); // 强制转换防截断
|
||||
|
||||
System.out.printf("平均分: %.2f(共 %d 名学生)\n", average, scores.size());
|
||||
}
|
||||
|
||||
/** 找最高分和最低分 */
|
||||
static void showMaxMin() {
|
||||
if (scores.isEmpty()) {
|
||||
System.out.println("暂无成绩记录。");
|
||||
return;
|
||||
}
|
||||
|
||||
int max = scores.get(0);
|
||||
int min = scores.get(0);
|
||||
|
||||
for (int s : scores) {
|
||||
if (s > max) max = s;
|
||||
if (s < min) min = s;
|
||||
}
|
||||
|
||||
System.out.println("最高分: " + max);
|
||||
System.out.println("最低分: " + min);
|
||||
}
|
||||
}
|
||||
117
week1/day05/Student.java
Normal file
117
week1/day05/Student.java
Normal file
@@ -0,0 +1,117 @@
|
||||
package day05;
|
||||
|
||||
/**
|
||||
* 第 5 天:面向对象(上)—— 类与对象、封装
|
||||
* 目标:掌握如何定义一个类,如何创建和使用对象
|
||||
*
|
||||
* 重点:
|
||||
* private 成员变量 + public getter/setter = 封装
|
||||
* 构造方法 = 初始化对象的快捷方式
|
||||
* this = 区分成员变量和局部变量
|
||||
*/
|
||||
|
||||
// ==================== Student 类定义 ====================
|
||||
class Student {
|
||||
|
||||
// 1. 私有成员变量(封装:外部不能直接访问)
|
||||
private String name;
|
||||
private int age;
|
||||
private String studentId; // 学号
|
||||
|
||||
// 2. 构造方法(与类同名,无返回值)
|
||||
// 无参构造
|
||||
public Student() {
|
||||
this.name = "未知";
|
||||
this.age = 0;
|
||||
this.studentId = "未分配";
|
||||
}
|
||||
|
||||
// 有参构造(支持创建对象时直接赋值)
|
||||
public Student(String name, int age, String studentId) {
|
||||
this.name = name;
|
||||
this.age = age;
|
||||
this.studentId = studentId;
|
||||
}
|
||||
|
||||
// 3. Getter / Setter(公开的访问入口)
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
// 可以在 setter 里加校验逻辑
|
||||
if (name == null || name.trim().isEmpty()) {
|
||||
System.out.println("⚠ 姓名不能为空!");
|
||||
return;
|
||||
}
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
if (age < 0 || age > 150) {
|
||||
System.out.println("⚠ 年龄不合理!");
|
||||
return;
|
||||
}
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public String getStudentId() {
|
||||
return studentId;
|
||||
}
|
||||
|
||||
public void setStudentId(String studentId) {
|
||||
this.studentId = studentId;
|
||||
}
|
||||
|
||||
// 4. 行为方法
|
||||
public void study(String subject) {
|
||||
System.out.println(name + " 正在学习 " + subject + "。");
|
||||
}
|
||||
|
||||
public void takeExam(String subject) {
|
||||
System.out.println(name + "(学号:" + studentId + ")正在参加 " + subject + " 考试。");
|
||||
}
|
||||
|
||||
public void introduce() {
|
||||
System.out.println("-----------------------------------");
|
||||
System.out.println("自我介绍:");
|
||||
System.out.println(" 姓名:" + name);
|
||||
System.out.println(" 年龄:" + age + " 岁");
|
||||
System.out.println(" 学号:" + studentId);
|
||||
System.out.println("-----------------------------------");
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 测试类 ====================
|
||||
class StudentTest {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("========== 面向对象练习 ==========\n");
|
||||
|
||||
// 1. 使用无参构造 + setter 创建对象
|
||||
Student s1 = new Student();
|
||||
s1.setName("张三");
|
||||
s1.setAge(20);
|
||||
s1.setStudentId("2024001");
|
||||
s1.introduce();
|
||||
s1.study("Java");
|
||||
s1.takeExam("面向对象程序设计");
|
||||
|
||||
// 2. 使用有参构造直接创建
|
||||
Student s2 = new Student("李四", 22, "2024002");
|
||||
s2.introduce();
|
||||
|
||||
// 3. 创建第三个学生
|
||||
Student s3 = new Student("王五", 19, "2024003");
|
||||
s3.introduce();
|
||||
s3.study("数据结构");
|
||||
|
||||
// 4. 演示数据校验
|
||||
System.out.println("\n--- 测试 data 校验 ---");
|
||||
s3.setAge(-5); // 触发校验
|
||||
s3.setName(""); // 触发校验
|
||||
}
|
||||
}
|
||||
145
week1/day06/AnimalHierarchy.java
Normal file
145
week1/day06/AnimalHierarchy.java
Normal file
@@ -0,0 +1,145 @@
|
||||
package day06;
|
||||
|
||||
/**
|
||||
* 第 6 天:面向对象(下)—— 继承、多态、接口、抽象类
|
||||
* 目标:理解 OOP 三大特性中的"继承"和"多态"
|
||||
*
|
||||
* 重点:
|
||||
* extends —— 单继承:子类拥有父类的属性和方法
|
||||
* @Override —— 方法重写:子类用自己的实现覆盖父类方法
|
||||
* 抽象类 —— 不能被 new,可以有抽象方法(留给子类实现)
|
||||
* 接口 —— 一组行为规范(方法签名),一个类可以实现多个接口
|
||||
* 多态 —— 父类引用指向子类对象:Animal a = new Dog();
|
||||
*/
|
||||
|
||||
// ==================== 1. 抽象父类 ====================
|
||||
abstract class Animal {
|
||||
protected String name;
|
||||
|
||||
public Animal(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
// 抽象方法:没有方法体,子类必须实现
|
||||
public abstract String makeSound();
|
||||
|
||||
// 普通方法:有方法体,子类可以继承也可以重写
|
||||
public void eat() {
|
||||
System.out.println(name + " 正在吃东西。");
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 2. 接口 ====================
|
||||
interface Pet {
|
||||
void play(); // 接口中的方法默认是 public abstract
|
||||
String getBreed(); // 品种
|
||||
}
|
||||
|
||||
// ==================== 3. 子类 Dog ====================
|
||||
class Dog extends Animal implements Pet {
|
||||
private String breed; // 品种
|
||||
|
||||
public Dog(String name, String breed) {
|
||||
super(name); // 调用父类构造方法(必须放在第一行)
|
||||
this.breed = breed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String makeSound() {
|
||||
return "汪汪汪!";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void play() {
|
||||
System.out.println(name + "(" + breed + ")兴奋地摇着尾巴,接住了飞盘!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBreed() {
|
||||
return breed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eat() {
|
||||
System.out.println(name + " 狼吞虎咽地吃着狗粮。");
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 4. 子类 Cat ====================
|
||||
class Cat extends Animal implements Pet {
|
||||
private String breed;
|
||||
|
||||
public Cat(String name, String breed) {
|
||||
super(name);
|
||||
this.breed = breed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String makeSound() {
|
||||
return "喵喵喵~";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void play() {
|
||||
System.out.println(name + "(" + breed + ")懒洋洋地拨弄着逗猫棒。");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getBreed() {
|
||||
return breed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eat() {
|
||||
System.out.println(name + " 优雅地小口吃着猫粮。");
|
||||
}
|
||||
}
|
||||
|
||||
// ==================== 测试类 ====================
|
||||
class AnimalTest {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("========== 动物继承体系演示 ==========\n");
|
||||
|
||||
// 1. 基本使用
|
||||
Dog wangcai = new Dog("旺财", "金毛");
|
||||
Cat miaomiao = new Cat("咪咪", "英短");
|
||||
|
||||
System.out.println("--- 各自叫 ---");
|
||||
System.out.println(wangcai.getName() + ":" + wangcai.makeSound());
|
||||
System.out.println(miaomiao.getName() + ":" + miaomiao.makeSound());
|
||||
|
||||
System.out.println("\n--- 各自吃 ---");
|
||||
wangcai.eat();
|
||||
miaomiao.eat();
|
||||
|
||||
System.out.println("\n--- 各自玩 ---");
|
||||
wangcai.play();
|
||||
miaomiao.play();
|
||||
|
||||
// 2. ★ 多态:父类引用指向子类对象
|
||||
System.out.println("\n--- 多态演示 ---");
|
||||
Animal[] zoo = { // Animal 类型的数组
|
||||
new Dog("阿黄", "中华田园犬"),
|
||||
new Cat("小花", "橘猫"),
|
||||
new Dog("小黑", "拉布拉多")
|
||||
};
|
||||
|
||||
for (Animal a : zoo) {
|
||||
// 运行时决定调用哪个子类的 makeSound(动态绑定)
|
||||
System.out.println(a.getName() + ":" + a.makeSound());
|
||||
a.eat();
|
||||
}
|
||||
|
||||
// 3. 接口引用
|
||||
System.out.println("\n--- 接口多态 ---");
|
||||
Pet[] pets = { wangcai, miaomiao };
|
||||
for (Pet p : pets) {
|
||||
System.out.print(p.getBreed() + " -> ");
|
||||
p.play();
|
||||
}
|
||||
}
|
||||
}
|
||||
157
week1/教案.md
Normal file
157
week1/教案.md
Normal file
@@ -0,0 +1,157 @@
|
||||
# 第一阶段教案:Java 核心基础速通(第 1 周)
|
||||
|
||||
> **学习周期**:7 天
|
||||
> **每日用时**:2-3 小时
|
||||
> **教学方法**:概念讲解(30min)→ 代码演示(30min)→ 动手练习(1-2h)
|
||||
> **最终产出**:命令行通讯录程序
|
||||
|
||||
---
|
||||
|
||||
## 每日教学大纲
|
||||
|
||||
### 第 1 天:Hello World —— 迈出第一步
|
||||
|
||||
**核心概念**:JDK/JRE/JVM 的关系、Java 跨平台原理、编译与运行
|
||||
|
||||
**教学重点**:
|
||||
1. JDK(开发工具包)包含 JRE(运行环境),JRE 包含 JVM(虚拟机)
|
||||
2. Java 程序先编译成 .class 字节码,再由 JVM 执行 —— "一次编译,到处运行"
|
||||
3. `javac` 是编译器,`java` 是启动器
|
||||
4. `public static void main(String[] args)` —— 程序的唯一入口
|
||||
|
||||
**代码示例** `day01/HelloWorld.java`:
|
||||
```java
|
||||
public class HelloWorld {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello, Java!");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**常见踩坑**:
|
||||
- IDEA 中右键 → Run 即可运行,无需手动配置环境变量
|
||||
- 文件名必须和 public 类名完全一致(包括大小写)
|
||||
|
||||
---
|
||||
|
||||
### 第 2 天:数据与运算 —— 让程序"算"起来
|
||||
|
||||
**核心概念**:基本数据类型、变量声明、运算符、字符串拼接
|
||||
|
||||
**教学重点**:
|
||||
1. 8 种基本类型:byte/short/int/long/float/double/char/boolean
|
||||
2. 变量声明三要素:类型 + 名称 + 值
|
||||
3. 算术运算符:`+ - * / %`,注意整数除法截断
|
||||
4. 字符串用 `String`(不是基本类型,是引用类型),`+` 可拼接
|
||||
|
||||
**练习项目**:`day02/Calculator.java` —— 一个简单的四则运算计算器
|
||||
|
||||
---
|
||||
|
||||
### 第 3 天:流程控制 —— 让程序"思考"起来
|
||||
|
||||
**核心概念**:条件判断、循环、分支选择
|
||||
|
||||
**教学重点**:
|
||||
1. `if / else if / else` —— 分支逻辑
|
||||
2. `switch` —— 多分支(适合固定值匹配)
|
||||
3. `for` 循环 —— 已知次数时使用
|
||||
4. `while` 循环 —— 未知次数时使用(先判断后执行)
|
||||
5. `do-while` 循环 —— 至少执行一次(先执行后判断)
|
||||
6. `break` 跳出循环,`continue` 跳过本次
|
||||
|
||||
**练习项目**:
|
||||
- `day03/MultiplicationTable.java` —— 打印 9×9 乘法表(for 嵌套)
|
||||
- `day03/GuessNumber.java` —— 猜数字游戏(while + if)
|
||||
|
||||
---
|
||||
|
||||
### 第 4 天:数组与方法 —— 组织数据与代码
|
||||
|
||||
**核心概念**:数组、动态数组、方法定义与调用
|
||||
|
||||
**教学重点**:
|
||||
1. 数组声明:`int[] arr = new int[10];`
|
||||
2. 数组下标从 0 开始,越界会抛 `ArrayIndexOutOfBoundsException`
|
||||
3. `ArrayList` 动态数组:`ArrayList<String> list = new ArrayList<>();`
|
||||
4. 方法的定义:`public static 返回类型 方法名(参数列表) { 方法体 }`
|
||||
5. 方法的调用:`方法名(实参);`
|
||||
6. 形参 vs 实参,值传递
|
||||
|
||||
**练习项目**:`day04/StudentScoreManager.java` —— 学生成绩管理器
|
||||
- 添加成绩、查看全部、计算平均分、查找最高/最低分
|
||||
|
||||
---
|
||||
|
||||
### 第 5 天:面向对象(上)—— 用类描述世界
|
||||
|
||||
**核心概念**:类与对象、构造方法、封装、this 关键字
|
||||
|
||||
**教学重点**:
|
||||
1. 类是模板,对象是实例 —— `new 类名()` 创建对象
|
||||
2. 成员变量 vs 局部变量
|
||||
3. 构造方法:与类同名,无返回值,用于初始化对象
|
||||
4. 封装:`private` 修饰成员变量 + `public` getter/setter
|
||||
5. `this` 关键字:代表当前对象,区分成员变量和局部变量
|
||||
|
||||
**练习项目**:`day05/Student.java` —— 定义 Student 类
|
||||
- 属性:姓名、年龄、学号(private)
|
||||
- 方法:学习、考试、自我介绍
|
||||
- 写测试类创建 3 个学生对象并调用方法
|
||||
|
||||
---
|
||||
|
||||
### 第 6 天:面向对象(下)—— 继承与多态
|
||||
|
||||
**核心概念**:继承、多态、接口、抽象类
|
||||
|
||||
**教学重点**:
|
||||
1. `extends` 继承:子类拥有父类的属性和方法(单继承)
|
||||
2. `super` 调用父类构造方法或成员
|
||||
3. 方法重写 `@Override`:子类重新定义父类方法
|
||||
4. 多态:父类引用指向子类对象 `Animal a = new Dog();`
|
||||
5. `abstract` 抽象类:不能实例化,可以有抽象方法和普通方法
|
||||
6. `interface` 接口:完全抽象,一个类可以实现多个接口
|
||||
|
||||
**练习项目**:`day06/AnimalHierarchy.java` —— 动物继承体系
|
||||
- 抽象父类 Animal(有 name 和抽象方法 makeSound)
|
||||
- 子类 Dog、Cat 重写 makeSound
|
||||
- 接口 Pet(有 play 方法),Dog 和 Cat 实现它
|
||||
|
||||
---
|
||||
|
||||
### 第 7 天:异常处理 + 集合框架 + 综合项目
|
||||
|
||||
**核心概念**:异常处理、集合框架(List/Map/Set)
|
||||
|
||||
**教学重点**:
|
||||
1. try-catch-finally 处理异常,防止程序崩溃
|
||||
2. `ArrayList` 有序列表(List)—— 可重复,有索引
|
||||
3. `HashMap` 键值对(Map)—— key 唯一,快速查找
|
||||
4. `HashSet` 无序集合(Set)—— 不可重复
|
||||
5. 泛型 `<T>`:编译期类型检查
|
||||
|
||||
**综合项目**:`addressbook/` —— 命令行通讯录
|
||||
- 封装 Contact 类
|
||||
- 使用 HashMap 存储联系人(以姓名为 key)
|
||||
- 菜单驱动的 CRUD 操作
|
||||
- 异常处理防止崩溃
|
||||
|
||||
---
|
||||
|
||||
## 教学方法建议
|
||||
|
||||
| 环节 | 时间 | 内容 |
|
||||
|------|------|------|
|
||||
| 概念导入 | 15min | 用生活类比引入概念(类=图纸,对象=房子) |
|
||||
| 代码演示 | 30min | 老师在 IDE 中边写边讲,每个语句解释为什么 |
|
||||
| 跟练 | 30min | 学员照着敲一遍,感受语法 |
|
||||
| 独立练习 | 1h | 不看参考代码,独立完成当日练习项目 |
|
||||
| 复盘 | 15min | 对比参考代码,找出差异和理解盲区 |
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **不要跳步**:每天的内容建立在前一天的基础上,确保当天掌握再前进
|
||||
2. **多犯错**:看到报错不要慌,仔细读错误信息是最快的进步方式
|
||||
3. **先思考后动手**:在写代码前,先用中文把思路写下来
|
||||
4. **代码量 > 看书量**:每天至少手敲 100 行代码,肌肉记忆很重要
|
||||
Reference in New Issue
Block a user