【问题标题】:java.lang.ArrayIndexOutOfBoundsException: 3 in a while loopjava.lang.ArrayIndexOutOfBoundsException: 3 在一个while循环
【发布时间】:2015-12-05 17:19:04
【问题描述】:

我遇到了这个异常,但我不知道如何解决它:

java.lang.ArrayIndexOutOfBoundsException: 3

while 循环中。这是我的代码:

public class NameSearch {
    static String[] names = new String[3];

    void populateStringArray() {
        names[0] = "Ben";
        names[1] = "Thor";
        names[2] = "Zoe";
        names[3] = "Kate";
    }

    public static void main(String[] args) {
        String pName;
        int max = 4;
        int current = 1;
        boolean found = false;

        Scanner scan = new Scanner(System.in);
        System.out.println("What player are you looking for?");
        pName = scan.next();
        while (found == false && current <= max) {
            if (names[current] == pName) {
                found = true;
            } else {
                current = current + 1;
            }
        }
        if (found == true) {
            System.out.println("Yes, they have a top score");
        } else {
            System.out.println("No, they do not have a top score");
        }
    }
}

该代码旨在要求用户输入一个名称,它将检查该名称是否在数组中(简而言之)。

我的 IDE (Eclipse) 说错误位于 if (names[current] == pName){ 行中。

【问题讨论】:

标签: java arrays string while-loop


【解决方案1】:

因为你有条件current &lt;= max。如果max4,那么这意味着current 可以等于4,并且数组中没有索引4。这就是错误来自names[current] 的原因,您正在尝试访问索引4 并且它不存在。您应该只使用&lt; 而不是&lt;= 或使用max = 3 而不是4

旁注:

  • 因为如果current 等于1 时,数组以索引0 开始 循环开始它永远不会查看数组中的第一个索引。
  • 当检查布尔值作为条件时,您可以将变量放在true 之前,而不是== true== false,或者在false 之前添加!。因此,在这种情况下,您可以使用 while(!found 而不是 while(found == false
  • 当递增int,而不是current = current + 1时,通常的做法是在递增1时使用current++,或者当递增超过1时使用+=(例如current +=2将递增current 2)。

【讨论】:

    【解决方案2】:

    问题在于这种情况:found == false &amp;&amp; current&lt;= max - 旁注:found == false 可以简化为 !false,并且仍然会得到相同的结果。 current&lt;=max 允许循环以current == max 运行,max 定义为 4。因此,您在names[4] 处读取,这是越界的。最简单的解决方案是将条件从current &lt;= max 更改为current&lt;maxcurrent 被初始化为 1。由于数组在 java 中是从 0 开始的,这将导致程序省略第一个名称,即names[0]

    还有一个旁注:使用常量作为max 是一种极易出错的方法。用names.length 初始化max

    【讨论】:

      【解决方案3】:

      这里:

      static String[] names = new String[3];
      

      您正在初始化一个 容量 包含三个项目的数组,而不是最大索引 3。要获得一个包含 0、1、2 和 3 的数组,这是四个项目,所以你需要像这样初始化数组:

      static String[] names = new String[4]; // (0-3)
      

      此外,循环和数组都是从零开始的,因此您需要从 0 而不是 1 的 current 开始循环您的数组。
      此外,最后,您需要在 while 循环中将 &lt;= 切换为 &lt;,因为我们希望它最多只能达到 3。

      【讨论】:

        【解决方案4】:

        当您需要在 03(含)之间对数组元素进行索引时,您将在 14(含)之间的循环中对数组元素进行索引。

        current 更改为以0 开头,将max 更改为3,您应该一切都好。

        如果有更好的选择,请考虑将您的姓名列表放在HashSet 中,并且根本不需要迭代。例如

        Set<String> names = new HashSet<String>();
        names.add("Ben");
        names.add("Thor");
        names.add("Zoe");
        names.add("Kate");
        
        if (names.contains(pName)) {
        //...
        

        如果名称的顺序很重要,那么您可以改用List,它也有一个contains 方法(只是通常不如Map 实现中的效率高。O(n) vs O(1) 通常)。如果列表中的名称数量很少,或者性能不是问题,那么这两种方法都无关紧要。

        【讨论】:

        • 您可能想要修复您的代码示例 ... ;P(在当前状态下无法编译)
        • @Tom 你的意思是因为它指的是pName 还是因为if 没有完成?其目的不是让代码自行编译,只是作为一个简短的 sn-p 来说明对原始代码进行哪些更改以使用比循环迭代更好的解决方案来检查玩家姓名。
        • 不,我的意思是 everyone 使用 " 表示字符串文字(而 ' 表示字符),所以你也应该这样做;P。
        • @Tom 大声笑,好点,会解决它,谢谢!我最近写了太多的 JavaScript,我们的 JS 风格指南要求字符串用单引号(令我永远感到沮丧)。
        【解决方案5】:

        您的while 循环需要修复:当您的current 等于max 时,它仍会检查不存在的name[4]

        此外,== 不是比较 2 Strings 的最佳方式。您必须使用 .equals() 方法,因为它比较 2 String 的值,而不是比较 2 对象引用。这就是您的while 循环应该如何修复:

        while (found == false && current< max){
        
            if (names[current].equals(pName)){
                found = true;
            } else {
                current = current + 1;
            }
        }
        

        【讨论】:

          猜你喜欢
          • 2015-10-25
          • 1970-01-01
          • 2019-03-08
          • 2016-01-11
          • 1970-01-01
          • 2022-10-12
          • 1970-01-01
          • 2011-10-12
          • 1970-01-01
          相关资源
          最近更新 更多