我的程序因 ArrayIndexOutofBoundsExeption 错误而失败

My program fails with ArrayIndexOutofBoundsExeption Error

您好,我的程序无法 运行 和 ArrayIndexOutofBoundsExeption。当我 运行 时出现此错误:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -35
at RoulleteChecker.main(RoulleteChecker.java:134)

这是我的代码:

import javax.swing.JOptionPane;
import javax.swing.JTextArea;

public class RoulleteChecker {

      public static void main( String args[] )
      {

          int a[] = new int[37];

          for ( long roll = 1; roll <=99999999; roll++ ) {      
             a[0] = 1 + ( int ) ( Math.random() * 34); 

             switch ( a[0] ) {

               case 0:
                  ++a[1];
                   break; 

                case 1:
                   ++a[2];
                  break;

                case 2:
                   ++a[3];
                   break;

                case 3:
                   ++a[4];
                   break;

                case 4:
                   ++a[5];
                   break;

                case 5:
                   ++a[6];
                   break;
                case 6:
                    ++a[7];
                    break;
                case 7:
                    ++a[8];
                    break;
                case 8:
                    ++a[9];
                    break;
                case 9:
                    ++a[10];
                    break;
                case 10:
                    ++a[11];
                    break;
                case 11:
                    ++a[12];
                    break;
                case 12:
                    ++a[13];
                    break;
                case 13:
                    ++a[14];
                    break;
                case 14:
                    ++a[15];
                    break;
                case 15:
                    ++a[16];
                    break;
                case 16:
                    ++a[17];
                    break;
                case 17:
                    ++a[18];
                    break;
                case 18:
                    ++a[19];
                    break;
                case 19:
                    ++a[20];
                    break;
                case 20:
                    ++a[21];
                    break;
                case 21:
                    ++a[22];
                    break;
                case 22:
                    ++a[23];
                    break;
                case 23:
                    ++a[24];
                    break;
                case 24:
                    ++a[25];
                    break;
                case 25:
                    ++a[26];
                    break;
                case 26:
                    ++a[27];
                    break;
                case 27:
                    ++a[28];
                    break;
                case 28:
                    ++a[29];
                    break;
                case 29:
                    ++a[30];
                    break;
                case 30:
                    ++a[31];
                    break;
                case 31:
                    ++a[32];
                    break;
                case 32:
                    ++a[33];
                    break;
                case 33:
                    ++a[34];
                    break;
                case 34:
                    ++a[35];
                    break;
             } 

         } 

         JTextArea outputArea = new JTextArea();

         outputArea.setText( "Lets see: " + a[0-35] );

         JOptionPane.showMessageDialog( null, outputArea,
             "Searching for the frequency: 99999999 times", JOptionPane.INFORMATION_MESSAGE );  
         System.exit( 1 );

     }  
} 

拜托,我的头要被这个炸了。我认为我的错误在 a 变量上。

这是Java:

 a[0-35]

实际意思是:

 a[-35]

是什么让您认为 -35 是一个有效的索引?你看---修复错误所需的所有信息都在那里-你只需要仔细阅读异常消息。它告诉你错误的位置,它告诉你无效的索引!

顺便说一句:请考虑您的 switch 语句。

你真的认为你需要写下一个或多或少的开关

case i:
  i++; 

?

错误来自这一行:

outputArea.setText( "Lets see: " + a[0-35] );

-符号是算术减号运算符。因此,0 - 35 是 -35,这当然不是有效索引。我猜你想打印 0 到 35 的 range,这可以用 Arrays.toString:

来完成
outputArea.setText( "Lets see: " + Arrays.toString(a));

首先,所有那个巨大的开关都可以用这个代替:

++a[a[0] + 1];

那么,正如其他人已经指出的那样,a[0 - 35] 并不是你想要的,它不会神奇地抢占数组的位置 0 到 35。它只是 0 减去 35 的数学结果,即 -35。数组中没有位置-35。

要将数组表示为字符串,我们可以使用 Java 8 个流:

IntStream.of(a).limit(36).boxed().collect(Collectors.toList()).toString().replace(", ", "\n")

这是做什么的:

  1. 这会将 int[] 转换为 IntStreamIntStream.of(a) 部分)。
  2. 让我们限制为仅获取前 36 个元素(因为您想要从 0 到 35 的元素)。这就是 .limit(36) 的作用。
  3. 然后 IntStream 将被转换为 Stream<Integer>.boxed())部分。
  4. 然后它会被转换成List<Integer>.collect(Collectors.toList()))部分。
  5. 然后它会被转换成一个String.toString()部分)。
  6. 由于 String 太长而无法在一行中显示,因此添加一些换行符是个好主意,这就是 .replace(", ", "\n") 所做的。

最后,你不需要 System.exit(1);,它在这里没有任何用处。

有了这个,这是你的结果代码:

import java.util.stream.Collectors;
import java.util.stream.IntStream;
import javax.swing.JOptionPane;
import javax.swing.JTextArea;

public class RoulleteChecker {

    public static void main(String args[]) {

        int a[] = new int[37];

        for (long roll = 1; roll <= 99999999; roll++) {
            a[0] = 1 + (int) (Math.random() * 34);
            ++a[a[0] + 1];
        }

        JTextArea outputArea = new JTextArea();

        outputArea.setText("Lets see: " + IntStream.of(a).limit(36).boxed().collect(Collectors.toList()).toString().replace(", ", "\n"));

        JOptionPane.showMessageDialog(null, outputArea,
                "Searching for the frequency: 99999999 times", JOptionPane.INFORMATION_MESSAGE);

    }
}

新的改进答案:

为了显示行号,我认为Streams 方法行不通,否则会过于复杂。因此,让我们改用专门的方法:

import javax.swing.JOptionPane;
import javax.swing.JTextArea;

public class RoulleteChecker {

    private static final int TIMES = 99999999;

    public static void main(String args[]) {

        int a[] = new int[36];

        for (long roll = 1; roll <= TIMES; roll++) {
            int r = (int) (Math.random() * a.length);
            ++a[r];
        }

        JTextArea outputArea = new JTextArea();

        outputArea.setText("Lets see:\n" + asString(a));

        JOptionPane.showMessageDialog(null, outputArea,
                "Searching for the frequency: " + TIMES + " times", JOptionPane.INFORMATION_MESSAGE);
    }

    private static String asString(int[] s) {
        StringBuilder sb = new StringBuilder(8 * s.length);
        for (int i = 0; i < s.length; i++) {
            sb.append(i + 1).append(": ").append(s[i]).append("\n");
        }
        return sb.toString();
    }
}

这里还有一些区别:

  • 由于数组的第0位只是暂时存放新生成的数,所以让我们把它从数组中取出来。这就是 r 变量的含义。因为我删除了数组的第 0 个位置,所以我删除了 ++a[a[0] + 1] 上的 + 1,它变成了简单的 ++a[r].

  • 我把次数(99999999)移到了一个常数。这样可以更轻松地根据需要更改它。

  • 同样,因为我删除了数组的第 0 个位置,所以我也从计算随机数的行中删除了 1 +。此外,我让它动态获取数组的大小,因此您无需在创建数组时和随机访问其位置之一时都跟踪数组大小。

  • asString 方法应该非常简单直接。唯一的陷阱是 i + 1,其中 + 1 的目的是显示从 1 而不是 0 开始的索引。

  • asString方法中StringBuilder的构造函数的参数只是对性能的总String大小估计,这不是重要的事情.