21、Java编程:数组、对象与命令行参数的运用

Java编程:数组、对象与命令行参数的运用

1. 文件操作与 PrintStream 构造函数

在 Java 编程中,文件操作是常见的任务。 PrintStream 构造函数在处理文件时表现出特定的行为。如果找不到 GuestList.txt 文件,它会创建一个新文件并准备写入数据;若文件已存在,它会覆盖现有文件,重新创建一个空文件用于写入。所以,若不想文件被覆盖,在调用 PrintStream 构造函数前需做好预防措施。

在读取文件时,若要从 Employees.txt 文件读取数据,需使用 new Scanner(new File("Employees.txt")) 。若误写成 new Scanner("Employees.txt") ,将无法连接到文件。而在写入文件时,使用 new PrintStream("GuestList.txt") 即可,若错误地加入 new File ,Java 编译器会报错。

2. 数组条件表达式的注意事项

在某些代码中,条件表达式 roomNum < 10 && guests[roomNum] != 0 需谨慎使用。若将其改为 guests[roomNum] != 0 && roomNum < 10 ,可能会引发问题。

3. 面向对象编程:Room 类

3.1 Room 类的定义

为了更好地管理酒店房间信息,引入了 Room 类。一个 Room 实例包含三个属性:房间内的客人数量、房间费率以及是否允许吸烟的标记。以下是 Room 类的代码:

import static java.lang.System.out;
import java.util.Scanner;
import java.text.NumberFormat;
public class Room {
    private int guests;
    private double rate;
    private boolean smoking;
    private static NumberFormat currency = 
        NumberFormat.getCurrencyInstance();
    public void readRoom(Scanner diskScanner) {
        guests = diskScanner.nextInt();
        rate = diskScanner.nextDouble();
        smoking = diskScanner.nextBoolean();
    }
    public void writeRoom() {
        out.print(guests);
        out.print("\t");
        out.print(currency.format(rate));
        out.print("\t");
        out.println(smoking ? "yes" : "no");
    }
}

3.2 Room 类的特点

  • 属性 guests 存储客人数量, rate 存储房间费率, smoking 是布尔类型,用于标记是否允许吸烟。
  • 静态字段 currency 是静态字段,使用 NumberFormat.getCurrencyInstance() 方法将房间费率格式化为货币形式。
  • 方法 readRoom 方法从文件中读取数据到对象的属性中; writeRoom 方法将对象的属性信息输出。

4. 使用 Room 类创建房间数组

4.1 创建房间数组的代码

要创建一个房间数组,可使用以下代码:

import static java.lang.System.out;
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
class ShowRooms {
    public static void main(String args[]) 
                                  throws IOException {
        Room rooms[];
        rooms = new Room[10];

        Scanner diskScanner = 
            new Scanner(new File("RoomList.txt"));
        for (int roomNum = 0; roomNum < 10; roomNum++) {
            rooms[roomNum] = new Room();
            rooms[roomNum].readRoom(diskScanner);
        }
        out.println("Room\tGuests\tRate\tSmoking?");
        for (int roomNum = 0; roomNum < 10; roomNum++) {
            out.print(roomNum);
            out.print("\t");
            rooms[roomNum].writeRoom();
        }
    }
}

4.2 创建对象数组的步骤

创建对象数组与创建基本类型数组有所不同,需完成三个步骤:
1. 声明数组变量 Room rooms[]; 声明一个 rooms 变量,用于引用数组。
2. 创建数组 rooms = new Room[10]; 为数组分配内存空间,包含 10 个元素。
3. 构造每个对象 :在循环中使用 rooms[roomNum] = new Room(); 为每个数组元素创建一个 Room 对象。

同时,还需为每个对象的属性赋值,可通过 readRoom 方法从文件中读取数据。以下是创建对象数组的步骤流程图:

graph TD;
    A[声明数组变量] --> B[创建数组];
    B --> C[构造每个对象];
    C --> D[填充对象属性];

4.3 简化创建步骤

可以将前两个步骤合并,如 Room rooms[] = new Room[10]; ,也可使用数组初始化器。

5. 数字格式化

在 Java 中,有多种方式可使数字显示更美观。例如, Listing 7 - 7 使用 printf Listing 10 - 1 使用 DecimalFormat 。而在 Room 类中,使用 NumberFormat 类的 getCurrencyInstance 方法来显示货币金额。

5.1 与其他格式化方式的比较

格式化方式 使用的类 创建方式 特点
Listing 10 - 1 DecimalFormat 构造函数 更具体的小数格式化
Room NumberFormat getCurrencyInstance 方法 方便创建货币格式

getCurrencyInstance 方法是工厂方法的一个例子,它能方便地创建常用对象,无需手动编写复杂的格式代码。

6. 条件运算符

Room 类的 writeRoom 方法中,使用了条件运算符 smoking ? "yes" : "no" 。条件运算符接受三个表达式,根据条件的真假返回其中一个表达式的值,类似于一个小型的 if 语句。

7. 命令行参数

7.1 命令行参数的概念

在早期,大多数程序员使用基于文本的开发界面。运行程序时,可在命令行输入额外信息,这些信息被称为命令行参数。例如,运行 MakeRandomNumsFile 程序时,可输入 java MakeRandomNumsFile MyNumberedFile.txt 5 ,程序会读取这两个额外信息并使用它们。

7.2 Java 程序中使用命令行参数

在 Java 程序的 main 方法中, String args[] 用于接收命令行参数。以下是使用命令行参数的代码示例:

import java.util.Random;
import java.io.PrintStream; 
import java.io.IOException;
class MakeRandomNumsFile {

   public static void main(String args[]) 
                                    throws IOException {
      Random generator = new Random(); 

      if (args.length < 2) {
         System.out.println
           ("Usage: MakeRandomNumsFile filename number");
         System.exit(1);
      }

      PrintStream printOut = new PrintStream(args[0]);
      int numLines = Integer.parseInt(args[1]);

      for (int count = 1; count <= numLines; count++) {
         printOut.println(generator.nextInt(10) + 1);
      }
   }
}

7.3 命令行参数的处理步骤

  1. 检查参数数量 :通过 args.length 检查命令行参数的数量是否符合要求。
  2. 获取参数值 args[0] 是文件名, args[1] 是生成随机数的行数。
  3. 转换参数类型 :由于命令行参数是字符串类型,需使用 Integer.parseInt 方法将其转换为整数类型。

7.4 错误处理

若用户输入的参数不符合要求,如忘记输入参数或输入非数字字符,程序可能会崩溃。在上述代码中,检查了参数数量,但对于输入非数字字符的情况,还需进一步处理。

综上所述,在 Java 编程中,合理运用数组、对象和命令行参数,能提高程序的灵活性和实用性。同时,需注意各种操作的细节和错误处理,以确保程序的稳定性。

8. 命令行参数的文件路径问题

8.1 不同操作系统的文件路径表示

在使用命令行参数指定文件路径时,不同操作系统有不同的路径表示方式。
- Windows :文件路径使用反斜杠 \ ,但在 Java 的字符串中,需使用双反斜杠 \\ 表示一个反斜杠。例如,要指定文件路径为 c:\MyNumberedFile.txt ,在 Java 代码中应写成 "c:\\MyNumberedFile.txt"
- Linux 和 Macintosh :文件路径使用正斜杠 / ,在 Java 字符串中直接使用一个正斜杠即可。例如,要指定 Macintosh 系统中 Documents 目录下的文件,可写成 "/Users/YourUserName/Documents/MyNumberedFile.txt"

8.2 文件保存位置

运行 MakeRandomNumsFile 程序后,生成的新文件 MyNumberedFile.txt 的保存位置取决于多种因素。若使用集成开发环境(IDE)且程序按项目划分,新文件通常位于项目文件夹中。可以修改代码来指定完整的文件路径,以确保文件保存到指定位置。

9. 命令行参数的类型转换

9.1 字符串转整数

MakeRandomNumsFile 程序中, args[1] 是一个字符串类型的命令行参数,需要将其转换为整数类型才能用于计数。使用 Integer.parseInt 方法可以实现这一转换,示例代码如下:

int numLines = Integer.parseInt(args[1]);

9.2 类型转换的风险

若用户输入的 args[1] 不是有效的数字字符串,如输入了字母或其他非数字字符,调用 Integer.parseInt 方法会抛出 NumberFormatException 异常。因此,在实际应用中,需要对输入进行验证和异常处理。

10. 命令行参数的错误检查

10.1 检查参数数量

MakeRandomNumsFile 程序中,首先检查命令行参数的数量是否足够。若参数数量小于 2,程序会输出使用说明并退出,代码如下:

if (args.length < 2) {
    System.out.println("Usage: MakeRandomNumsFile filename number");
    System.exit(1);
}

10.2 检查参数类型

除了检查参数数量,还需要检查参数的类型是否符合要求。例如, args[1] 必须是一个有效的整数。在当前代码中,虽然没有对 NumberFormatException 进行处理,但可以在后续优化中添加相应的异常处理逻辑。以下是添加异常处理后的代码示例:

import java.util.Random;
import java.io.PrintStream; 
import java.io.IOException;

class MakeRandomNumsFile {
    public static void main(String args[]) throws IOException {
        Random generator = new Random();
        if (args.length < 2) {
            System.out.println("Usage: MakeRandomNumsFile filename number");
            System.exit(1);
        }
        PrintStream printOut = new PrintStream(args[0]);
        int numLines;
        try {
            numLines = Integer.parseInt(args[1]);
        } catch (NumberFormatException e) {
            System.out.println("The second argument must be a valid integer.");
            System.exit(1);
        }
        for (int count = 1; count <= numLines; count++) {
            printOut.println(generator.nextInt(10) + 1);
        }
    }
}

10.3 错误检查的流程

以下是命令行参数错误检查的流程图:

graph TD;
    A[开始] --> B[检查参数数量];
    B -- 参数数量不足 --> C[输出使用说明并退出];
    B -- 参数数量足够 --> D[尝试转换参数类型];
    D -- 转换成功 --> E[执行程序逻辑];
    D -- 转换失败 --> F[输出错误信息并退出];

11. 总结

通过以上内容,我们了解了 Java 编程中数组、对象和命令行参数的使用方法和注意事项。以下是一个总结表格:
| 主题 | 关键知识点 | 示例代码 |
| ---- | ---- | ---- |
| 文件操作 | PrintStream 构造函数处理文件的创建和覆盖;读取文件使用 Scanner | PrintStream printOut = new PrintStream("GuestList.txt"); Scanner diskScanner = new Scanner(new File("Employees.txt")); |
| 数组条件表达式 | 注意条件表达式的顺序,避免错误 | roomNum < 10 && guests[roomNum] != 0 |
| 面向对象编程 | Room 类的定义和使用;创建对象数组的步骤 | public class Room {...} Room rooms[] = new Room[10]; |
| 数字格式化 | 使用 NumberFormat 类的 getCurrencyInstance 方法显示货币金额 | NumberFormat currency = NumberFormat.getCurrencyInstance(); out.print(currency.format(rate)); |
| 条件运算符 | 接受三个表达式,根据条件返回其中一个表达式的值 | smoking ? "yes" : "no" |
| 命令行参数 | 从命令行获取额外信息;参数类型转换和错误检查 | public static void main(String args[]) {...} int numLines = Integer.parseInt(args[1]); |

在实际编程中,要根据具体需求合理运用这些知识,并注意处理可能出现的错误和异常,以提高程序的健壮性和可靠性。同时,要根据不同的操作系统和环境,正确处理文件路径和参数输入,确保程序在各种情况下都能正常运行。

通过掌握这些知识,我们可以编写出更加灵活、高效和稳定的 Java 程序,应对各种复杂的编程场景。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值