Java-Varargs | Whiletrue| Scanner-退出无限while循环

问题描述

在描述我的问题之前,我想告诉您我熟悉ArrayList,但是我很好奇这与varargs一起工作的方式。

我的问题是: 当我在扫描仪输入中使用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方法创建具有不确定长度的数组。 现在知道由varargs创建的数组的初始长度为零,如果我想使用Scanner方法增加数组的长度,我不确定在哪里可以操纵该长度。 我知道ArrayList更加灵活,可以用来解决此问题,但是在一维数组课程的最后有一个问题,其中一项任务是创建未定义长度的数组,这使我可以用一个维数组。

解决方法

您的问题

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

您的问题在于,

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 < numbers.length始终求值为0 < 0,即false。因此,您的while循环无限地进行


变量(可变Arity方法)

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

  • 为什么我的代码会编译

但是您确实提到“ varargs”,我将借此机会让您了解有关该主题的更多细节。

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

尽管有一点语法上的收获:

OCP Java SE 8 Preparation text-book(斯科特·塞里科夫,珍妮·博雅斯基):

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

Effective Java,3rd Edition(由Joshua Bloch撰写):

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

这就是为什么您的代码会编译的原因。如果您的方法中有Type...varargs参数,则可以完全忽略(即您正在执行的操作),并且相应的(按上述定义)隐式值为分配给该参数。

,

您正在将一个空数组隐式传递给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();
}