【问题标题】:Java - Varargs|While(true)|Scanner - exiting infinite while loopJava - Varargs|While(true)|Scanner - 退出无限 while 循环
【发布时间】:2020-09-26 15:57:27
【问题描述】:

在描述我的问题之前,我想让您知道我对 ArrayList 很熟悉,但我很好奇它是如何与 varargs 一起工作的。

我的问题是: 当我使用带有扫描仪输入的可变参数时,我无法退出输入值为零(变量类型为 int)的无限循环。

我试过了: 用一个简单的“如果输入数 == 0 --> 从循环中中断”来退出无限循环。我不明白为什么这不起作用。我应该对代码进行哪些更改?

我尝试过的一些代码:

static Scanner scanner = new Scanner(System.in);

public static void main(String[] args) {
    createIntArray();
}

public static void createIntArray(int... numbers) {
    System.out.println("Enter numbers:");
        while (true) {
            for (int i = 0; i < numbers.length; i++) {
                numbers[i] = scanner.nextInt();
                if (numbers[i] == 0) {
                    break;
                }
            }
    }
}

为我的问题添加更多背景信息: 我读了一本 Java 书籍,其中关于一维数组的课程以一个未解决的练习问题结束,该问题是关于读取 1-100 之间的整数并计算出现次数。输入应以 0 结尾。因此,未定义数组长度。在单维数组课程中,可变参数被描述为具有可变数量参数的数组。我了解未设置参数的数量。我在想我可以使用 varargs 使用 Scanner 方法创建长度未定义的数组。 现在知道由可变参数创建的数组的初始长度为零,如果我想使用 Scanner 方法来增加数组长度,我不确定在哪里可以操纵长度。 我知道 ArrayList 更灵活,可以用来解决这个问题,但是在单维数组课程结束时有一个问题,其中一项任务是创建未定义长度的数组,这让我觉得这可以用一个维数组也是。

【问题讨论】:

  • 你没有传递任何参数,所以numbers是一个空数组,你不能给它赋值
  • 您确定您的代码与您发布的完全一致吗?因为您在没有传递任何参数的情况下调用 createIntArray(),所以 for 循环甚至不会运行。在这种情况下,也不确定将 N 个整数作为可变参数传递的意义何在。传递一个整数参数并在循环中使用它来代替numbers.length 会起作用。
  • numbers.length 为0,你不进入for循环,while循环一遍又一遍

标签: java input infinite-loop variadic-functions exit


【解决方案1】:

您的问题与可变参数(也称为“可变参数方法”)无关。

你的问题是,在:

static Scanner scanner = new Scanner(System.in);

public static void main(String[] args) {
    createIntArray();
}

public static void createIntArray(int... numbers) {
    System.out.println("Enter numbers:");
    
    while (true) {
        for (int i = 0; i < numbers.length; i++) {
            numbers[i] = scanner.nextInt();
            if (numbers[i] == 0) {
                break;
            }
        }
    }
}

永远不会输入for loop,因此,您永远不会从while 中突破。

for loop 的主体永远不会被执行的原因是,i &lt; numbers.length 的计算结果总是0 &lt; 0,即false。因此,您的while 循环无限 进行,永远不会进入for


Varargs(可变参数方法)

你不问这个问题,这可能(我认为 - 很可能)引起更多关注:

  • 为什么我的代码会编译

但您确实提到了“可变参数”,我将借此机会让您了解有关该主题的更多详细信息。

Type...varargsType[] varargs 编译成相同的代码。

不过有一点语法问题:

OCP Java SE 8 Preparation text-book(Scott Selikoff、Jeanne Boyarsky):

调用具有可变长度参数的方法应该发生在字面上 - 可变数量的元素 [0..n],而调用数组类型参数的方法,必须通过提供一个数组作为参数来发生。

Effective Java, 3rd Edition(约书亚·布洛赫):

可变参数工具的工作原理是首先创建一个数组,其大小是在调用站点传递的参数数量,然后将参数值放入数组中,最后将数组传递给方法。

这就是你的代码编译的原因。如果您的方法中有Type...varargs 参数,则可以省略相应的显式参数(这就是您正在做的事情),并且相应的(对于上述定义)隐式值将被分配给那个参数。

【讨论】:

    【解决方案2】:

    您将一个空数组隐式传递给createIntArray。因此,for 循环不会执行(因为numbers.length0),并且永远不会到达 break 语句。

    您可以从中返回一个数组,而不是将数组传递给方法:

    public static void main(String[] args) {
        int[] numbers = createIntArray();
    }
    
    public static int[] createIntArray() {
        System.out.println("Enter numbers:");
        List<Integer> list = new LinkedList<>();
        while (true) {
            int num = scanner.nextInt();
            if (num == 0) {
                break;
            }
            list.add(num);
        }
        return list.stream().mapToInt(Integer::intValue).toArray();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-20
      • 2014-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多