5 changed files with 211 additions and 0 deletions
@ -0,0 +1,66 @@ |
|||||
|
abstract class Shape { |
||||
|
public abstract double getArea(); |
||||
|
} |
||||
|
|
||||
|
class Circle extends Shape { |
||||
|
private double radius; |
||||
|
|
||||
|
public Circle(double radius) { |
||||
|
this.radius = radius; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public double getArea() { |
||||
|
return Math.PI * radius * radius; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class Rectangle extends Shape { |
||||
|
private double width; |
||||
|
private double height; |
||||
|
|
||||
|
public Rectangle(double width, double height) { |
||||
|
this.width = width; |
||||
|
this.height = height; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public double getArea() { |
||||
|
return width * height; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class Triangle extends Shape { |
||||
|
private double base; |
||||
|
private double height; |
||||
|
|
||||
|
public Triangle(double base, double height) { |
||||
|
this.base = base; |
||||
|
this.height = height; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public double getArea() { |
||||
|
return 0.5 * base * height; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
class ShapeUtil { |
||||
|
public static void printArea(Shape shape) { |
||||
|
double area = shape.getArea(); |
||||
|
System.out.println("该图形的面积是: " + area); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public class AreaCalculator { |
||||
|
public static void main(String[] args) { |
||||
|
Shape circle = new Circle(5.0); |
||||
|
Shape rectangle = new Rectangle(4.0, 6.0); |
||||
|
Shape triangle = new Triangle(3.0, 8.0); |
||||
|
|
||||
|
System.out.println("--- 图形面积计算 ---"); |
||||
|
ShapeUtil.printArea(circle); |
||||
|
ShapeUtil.printArea(rectangle); |
||||
|
ShapeUtil.printArea(triangle); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,117 @@ |
|||||
|
import java.net.URI; |
||||
|
import java.net.http.HttpClient; |
||||
|
import java.net.http.HttpRequest; |
||||
|
import java.net.http.HttpResponse; |
||||
|
import java.time.LocalDate; |
||||
|
import java.time.format.DateTimeFormatter; |
||||
|
|
||||
|
public class GreenlandHistoryWeather { |
||||
|
|
||||
|
public static void main(String[] args) { |
||||
|
System.out.println("🚀 开始获取格陵兰岛历史天气数据..."); |
||||
|
|
||||
|
// --- 配置区域 ---
|
||||
|
double latitude = 64.18; // 努克 (Nuuk) 纬度
|
||||
|
double longitude = -51.69; // 努克 (Nuuk) 经度
|
||||
|
|
||||
|
// --- 设定历史时间段 ---
|
||||
|
// 这里是你之前设置的 2025 年 1 月
|
||||
|
LocalDate startDate = LocalDate.of(2025, 12, 1); |
||||
|
LocalDate endDate = LocalDate.of(2026, 1, 31); |
||||
|
|
||||
|
String dateStartStr = startDate.format(DateTimeFormatter.ISO_LOCAL_DATE); |
||||
|
String dateEndStr = endDate.format(DateTimeFormatter.ISO_LOCAL_DATE); |
||||
|
|
||||
|
System.out.println("📅 查询时间段: " + dateStartStr + " 至 " + dateEndStr); |
||||
|
System.out.println("📍 地点: 格陵兰岛 - 努克 (Nuuk)\n"); |
||||
|
|
||||
|
// --- 构建 API URL ---
|
||||
|
// ⚠️ 关键修改:使用 archive-api.open-meteo.com/v1/archive 专门获取历史数据
|
||||
|
String apiUrl = String.format( |
||||
|
"https://archive-api.open-meteo.com/v1/archive?latitude=%f&longitude=%f" + |
||||
|
"&start_date=%s&end_date=%s" + |
||||
|
"&daily=temperature_2m_max,temperature_2m_min,precipitation_sum" + |
||||
|
"&timezone=auto", |
||||
|
latitude, longitude, dateStartStr, dateEndStr |
||||
|
); |
||||
|
|
||||
|
HttpClient client = HttpClient.newHttpClient(); |
||||
|
HttpRequest request = HttpRequest.newBuilder() |
||||
|
.uri(URI.create(apiUrl)) |
||||
|
.GET() |
||||
|
.build(); |
||||
|
|
||||
|
try { |
||||
|
// 发送请求
|
||||
|
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); |
||||
|
|
||||
|
if (response.statusCode() == 200) { |
||||
|
String json = response.body(); |
||||
|
parseAndPrintHistory(json); |
||||
|
} else { |
||||
|
System.out.println("❌ 请求失败,状态码: " + response.statusCode()); |
||||
|
System.out.println("返回信息: " + response.body()); |
||||
|
System.out.println("\n💡 提示:如果状态码是 400,请检查日期是否超出了该站点的数据记录范围。"); |
||||
|
} |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
System.out.println("❌ 发生网络或程序错误: "); |
||||
|
e.printStackTrace(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// --- 解析并打印数据 ---
|
||||
|
private static void parseAndPrintHistory(String json) { |
||||
|
System.out.println("✅ 数据获取成功!解析结果如下:\n"); |
||||
|
System.out.printf("%-12s | %-10s | %-10s | %-10s%n", "日期", "最高温(°C)", "最低温(°C)", "降水(mm)"); |
||||
|
System.out.println("-------------------------------------------------------"); |
||||
|
|
||||
|
// 【关键】API 返回的日期字段名是 "time",不是 "date"
|
||||
|
String[] dates = extractArray(json, "time"); |
||||
|
|
||||
|
String[] maxTemps = extractArray(json, "temperature_2m_max"); |
||||
|
String[] minTemps = extractArray(json, "temperature_2m_min"); |
||||
|
String[] precip = extractArray(json, "precipitation_sum"); |
||||
|
|
||||
|
int count = Math.min(dates.length, maxTemps.length); |
||||
|
|
||||
|
if (count == 0) { |
||||
|
System.out.println("⚠️ 警告:未解析到数据。可能是该时间段无记录,或 JSON 结构变化。"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
for (int i = 0; i < count; i++) { |
||||
|
// 清理日期字符串两边的引号
|
||||
|
String dateClean = dates[i].replace("\"", ""); |
||||
|
|
||||
|
System.out.printf("%-12s | %-10s | %-10s | %-10s%n", |
||||
|
dateClean, |
||||
|
maxTemps[i], |
||||
|
minTemps[i], |
||||
|
precip[i] |
||||
|
); |
||||
|
} |
||||
|
System.out.println("-------------------------------------------------------"); |
||||
|
System.out.println("💡 任务完成!共获取 " + count + " 天的数据。"); |
||||
|
} |
||||
|
|
||||
|
// --- 辅助方法:简易 JSON 数组提取器 ---
|
||||
|
private static String[] extractArray(String json, String key) { |
||||
|
String searchKey = "\"" + key + "\":["; |
||||
|
int startIndex = json.indexOf(searchKey); |
||||
|
|
||||
|
// 如果找不到键,返回空数组
|
||||
|
if (startIndex == -1) return new String[0]; |
||||
|
|
||||
|
startIndex += searchKey.length(); |
||||
|
int endIndex = json.indexOf("]", startIndex); |
||||
|
|
||||
|
if (endIndex == -1) return new String[0]; |
||||
|
|
||||
|
String arrayContent = json.substring(startIndex, endIndex); |
||||
|
|
||||
|
// 按逗号分割,并去除可能的空白字符
|
||||
|
if (arrayContent.trim().isEmpty()) return new String[0]; |
||||
|
return arrayContent.split(","); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,5 @@ |
|||||
|
在需求分析阶段,我通过AI明确了以抽象类 Shape 为核心的设计思路,指导定义了 getArea() 抽象方法,并确立了 Circle、Rectangle、Triangle 的继承体系,为实验奠定了框架基础。 |
||||
|
|
||||
|
在代码实现阶段,AI 生成了所有类的基础代码,解决了“类名与文件名不一致”及“参数传递错误”等编译问题,并提供了可直接运行的测试代码,显著提升了编码效率。 |
||||
|
|
||||
|
在类图设计与报告撰写环节,AI 协助绘制了 UML 类图,并清晰解释了“组合 vs 继承”的核心区别,帮助我顺利完成了实验报告的理论分析部分。 |
||||
|
After Width: | Height: | Size: 163 KiB |
@ -0,0 +1,23 @@ |
|||||
|
实验报告:图形面积计算器的设计与实现 |
||||
|
一、实验目的 |
||||
|
掌握Java面向对象编程(OOP)的核心概念:抽象类、继承、多态。 |
||||
|
理解并应用单一职责原则进行代码重构。 |
||||
|
学会绘制UML类图以描述类与类之间的关系。 |
||||
|
探讨组合与继承在设计模式中的应用场景。 |
||||
|
二、实验内容 |
||||
|
设计并实现一个图形面积计算器,要求如下: |
||||
|
定义一个抽象类 Shape,包含抽象方法 getArea()。 |
||||
|
创建 Circle(圆形)、Rectangle(矩形)、Triangle(三角形)三个具体类继承 Shape,并实现面积计算逻辑。 |
||||
|
编写工具类 ShapeUtil,利用多态特性统一打印不同图形的面积。 |
||||
|
绘制类图并分析设计思路。 |
||||
|
三、核心代码实现 |
||||
|
抽象类 Shape:定义了所有图形的通用行为 getArea(),强制子类必须实现该逻辑。 |
||||
|
多态的应用:在 ShapeUtil.printArea(Shape shape) 方法中,参数类型为父类 Shape,但在运行时可以根据传入的实际对象(如 Circle 或 Rectangle)动态调用对应的 getArea() 方法。 |
||||
|
四、类图设计 |
||||
|
继承关系:Circle、Rectangle、Triangle 均继承自 Shape,体现了“是一个”的关系。 |
||||
|
依赖关系:ShapeUtil 通过方法参数依赖 Shape 类,体现了工具类对抽象接口的调用。 |
||||
|
|
||||
|
|
||||
|
实验反思 |
||||
|
AI在代码生成、错误排查和文档撰写中发挥了关键作用。例如,它快速解决了“类名与文件名不一致”的编译问题,并提供了可运行的测试代码,大幅缩短了调试时间。但我也意识到,AI生成的代码需结合具体需求调整,不能盲目依赖。此外,AI对“组合与继承”等理论概念的解释,帮助我弥补了知识盲点,但需进一步结合教材深入理解其应用场景。本次实验不仅巩固了OOP知识,更让我体会到AI工具在工程实践中的价值与边界。未来,我将更注重理论与工具的结合,以提升编程效率与代码质量。 |
||||
|
|
||||
Loading…
Reference in new issue