
本文详细介绍了如何在Java中处理异构用户输入数据,利用多态性将不同类型的对象(如`Plant`和`Flower`)存储在同一个`ArrayList`中。通过解析用户输入的字符串,动态创建对象并将其添加到集合,最后使用统一的方法遍历并打印集合中所有对象的详细信息,从而展示了面向对象设计与集合框架的强大结合。
在Java应用程序开发中,我们经常需要从用户那里获取不同格式的数据,并将其存储为相应的对象。当这些对象具有共同的基类但又各自拥有独特的属性时,如何有效地解析、存储和管理它们就成为了一个关键问题。本教程将以一个具体的植物园管理示例,深入探讨如何利用Java的面向对象特性(特别是多态性)和集合框架(ArrayList),来优雅地解决这类异构数据处理的挑战。我们将学习如何读取多行用户输入,根据输入类型动态创建对象,并将这些不同类型的对象统一存储在一个ArrayList中,最终实现对所有对象的统一遍历和信息展示。
为了实现上述目标,我们需要理解并应用以下几个核心Java概念:
Java中的多态性允许我们使用父类类型的引用来指向子类对象。这意味着,一个声明为ArrayList<Plant>的集合,不仅可以存储Plant类的实例,也可以存储其任何子类(如Flower类)的实例。这种能力是处理异构数据集合的关键,它允许我们以统一的方式管理不同类型的对象。当调用集合中对象的共享方法(如本例中的printInfo())时,Java的动态方法调度机制会自动调用相应子类重写的方法,从而实现“一个接口,多种实现”。
立即学习“Java免费学习笔记(深入)”;
从用户处读取多行、多字段的字符串输入是常见需求。
从字符串中解析出的数据往往需要转换为特定的数据类型,以便赋值给对象的属性。
我们将通过一个具体的PlantArrayListExample程序来演示上述概念的实现。
首先,我们需要定义Plant基类和Flower派生类。Plant类包含植物名称和成本,Flower类继承Plant并额外包含是否为一年生植物和花的颜色。两个类都将实现一个printInfo()方法来打印各自的详细信息。
Plant.java
PHP经典实例(第2版)能够为您节省宝贵的Web开发时间。有了这些针对真实问题的解决方案放在手边,大多数编程难题都会迎刃而解。《PHP经典实例(第2版)》将PHP的特性与经典实例丛书的独特形式组合到一起,足以帮您成功地构建跨浏览器的Web应用程序。在这个修订版中,您可以更加方便地找到各种编程问题的解决方案,《PHP经典实例(第2版)》中内容涵盖了:表单处理;Session管理;数据库交互;使用We
453
public class Plant {
private String plantName;
private int plantCost; // 假设成本为整数
public Plant() {
this.plantName = "unknown";
this.plantCost = 0;
}
public void setPlantName(String plantName) {
this.plantName = plantName;
}
public void setPlantCost(int plantCost) {
this.plantCost = plantCost;
}
public String getPlantName() {
return plantName;
}
public int getPlantCost() {
return plantCost;
}
public void printInfo() {
System.out.println("Plant Name: " + plantName + ", Cost: " + plantCost);
}
}Flower.java
public class Flower extends Plant {
private boolean isAnnual;
private String colorOfFlowers;
public Flower() {
super(); // 调用父类构造器
this.isAnnual = false;
this.colorOfFlowers = "none";
}
public void setAnnual(boolean isAnnual) { // 命名更清晰
this.isAnnual = isAnnual;
}
public void setColorOfFlowers(String colorOfFlowers) {
this.colorOfFlowers = colorOfFlowers;
}
public boolean getIsAnnual() {
return isAnnual;
}
public String getColorOfFlowers() {
return colorOfFlowers;
}
@Override
public void printInfo() {
System.out.println("Flower Name: " + getPlantName() + ", Cost: " + getPlantCost() +
", Annual: " + isAnnual + ", Color: " + colorOfFlowers);
}
}在main方法中,我们需要创建一个Scanner对象来读取用户输入,以及一个ArrayList<Plant>来存储Plant和Flower对象。输入循环将持续读取,直到用户输入-1。
import java.util.Scanner;
import java.util.ArrayList;
public class PlantArrayListExample {
// ... printArrayList method will be here ...
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
ArrayList<Plant> myGarden = new ArrayList<Plant>();
String inputLine; // 用于存储每行输入
System.out.println("Enter plant or flower information (e.g., 'plant Spirea 10' or 'flower Hydrangea 30 false lilac'). Enter -1 to finish:");
// 首次读取一行输入
inputLine = scnr.nextLine();
while (!inputLine.equals("-1")) {
// ... 解析和对象创建逻辑 ...
// 读取下一行输入
inputLine = scnr.nextLine();
}
// ... 打印集合内容 ...
scnr.close(); // 关闭Scanner
}
}在while循环内部,使用String.split(" ")将当前行输入分割成字符串数组。
String[] info = inputLine.split(" ");
if (info.length == 0) { // 处理空行
inputLine = scnr.nextLine();
continue;
}根据info[0](第一个字段,表示类型)的值,判断是创建Plant对象还是Flower对象,并根据后续字段为对象的属性赋值。注意数据类型的转换。
String type = info[0].toLowerCase(); // 获取类型并转为小写
String plantName = info[1];
int plantCost = Integer.parseInt(info[2]); // 转换为int
if (type.equals("plant")) {
Plant p = new Plant();
p.setPlantName(plantName);
p.setPlantCost(plantCost);
myGarden.add(p);
} else if (type.equals("flower")) {
// 确保有足够的字段来解析花的信息
if (info.length >= 5) {
boolean isAnnual = Boolean.parseBoolean(info[3]); // 转换为boolean
String colorOfFlowers = info[4];
Flower f = new Flower();
f.setPlantName(plantName);
f.setPlantCost(plantCost);
f.setAnnual(isAnnual); // 使用更清晰的setter
f.setColorOfFlowers(colorOfFlowers);
myGarden.add(f);
} else {
System.err.println("Error: Incomplete flower information: " + inputLine);
}
} else {
System.err.println("Warning: Unknown plant/flower type: " + inputLine);
}无论是Plant对象还是Flower对象,都统一通过myGarden.add()方法添加到ArrayList<Plant>中。
定义一个静态方法printArrayList,它接收ArrayList<Plant>作为参数。通过遍历集合并调用每个元素的printInfo()方法,可以实现多态打印。
public static void printArrayList(ArrayList<Plant> myGarden) {
System.out.println("\n--- My Garden Contents ---");
for (Plant plant : myGarden) { // 使用增强for循环更简洁
plant.printInfo(); // 多态调用,根据实际对象类型执行对应的printInfo()
}
System.out.println("--------------------------");
}将上述所有部分组合起来,构成完整的PlantArrayListExample.java程序。
PlantArrayListExample.java
import java.util.Scanner;
import java.util.ArrayList;
public class PlantArrayListExample {
/**
* Prints the information of all Plant (or Flower) objects in the given ArrayList.
* Utilizes polymorphism to call the appropriate printInfo() method for each object.
* @param myGarden The ArrayList of Plant objects to print.
*/
public static void printArrayList(ArrayList<Plant> myGarden) {
System.out.println("\n--- My Garden Contents ---");
if (myGarden.isEmpty()) {
System.out.println("The garden is empty.");
return;
}
for (Plant plant : myGarden) {
plant.printInfo(); // Polymorphic call
}
System.out.println("--------------------------");
}
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
ArrayList<Plant> myGarden = new ArrayList<Plant>();
String inputLine;
System.out.println("Welcome to My Garden Manager!");
System.out.println("Enter plant or flower information. Use format:");
System.out.println(" 'plant <name> <cost>' (e.g., plant Spirea 10)");
System.out.println(" 'flower <name> <cost> <isAnnual> <color>' (e.g., flower Hydrangea 30 false lilac)");
System.out.println("Enter -1 to finish input.");
System.out.println("--------------------------------------------------");
// 首次读取一行输入
inputLine = scnr.nextLine();
while (!inputLine.equals("-1")) {
// 跳过空行
if (inputLine.trim().isEmpty()) {
inputLine = scnr.nextLine();
continue;
}
String[] info = inputLine.split(" ");
// 检查输入字段数量是否足够
if (info.length < 3) {
System.err.println("Error: Insufficient data for input: " + inputLine);
inputLine = scnr.nextLine();
continue;
}
try {
String type = info[0].toLowerCase();
String plantName = info[1];
int plantCost = Integer.parseInt(info[2]); // 尝试将成本字符串转换为整数
if (type.equals("plant")) {
Plant p = new Plant();
p.setPlantName(plantName);
p.setPlantCost(plantCost);
myGarden.add(p);
} else if (type.equals("flower")) {
// 确保花有足够的字段
if (info.length >= 5) {
boolean isAnnual = Boolean.parseBoolean(info[3]);
String colorOfFlowers = info[4];
Flower f = new Flower();
f.setPlantName(plantName);
f.setPlantCost(plantCost);
f.setAnnual(isAnnual);
f.setColorOfFlowers(colorOfFlowers);
myGarden.add(f);
} else {
System.err.println("Error: Incomplete flower information, expected 5 fields: " + inputLine);
}
} else {
System.err.println("Warning: Unknown plant/flower type encountered: " + inputLine);
}
} catch (NumberFormatException e) {
System.err.println("Error: Invalid cost format. Please enter a number for cost. Input: " + inputLine);
} catch (Exception e) { // 捕获其他潜在异常
System.err.println("An unexpected error occurred while processing input: " + inputLine + " - " + e.getMessage());
}
// 读取下一行输入
inputLine = scnr.nextLine();
}
// 调用方法打印myGarden中的所有元素
printArrayList(myGarden);
scnr.close(); // 关闭Scanner,释放资源
System.out.println("Program finished. Goodbye!");
}
}本教程通过一个实际的Java植物园管理系统示例,全面展示了如何结合Java的多态性、ArrayList集合以及字符串解析技术来有效地处理异构用户输入数据。我们学习了如何根据输入类型动态创建不同的对象,并将它们统一存储在泛型集合中,最后通过多态调用实现统一的打印逻辑。掌握这些技术对于开发灵活、可扩展的Java应用程序至关重要。通过遵循上述实现步骤和最佳实践,开发者可以构建出更加健壮和用户友好的应用程序。
以上就是Java中异构数据处理与多态集合应用指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号