【问题标题】:My program fails with ArrayIndexOutofBoundsExeption Error我的程序因 ArrayIndexOutofBoundsExeption 错误而失败
【发布时间】:2015-03-07 17:57:50
【问题描述】:

您好,我的程序无法使用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 变量上。

【问题讨论】:

  • 你觉得这个a[0-35]有什么作用?
  • 巨大的开关块可以改成1-3行代码。
  • 通过迭代来打印数组的内容。删除 a[0-35]

标签: java swing indexoutofboundsexception


【解决方案1】:

错误来自这一行:

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

- 符号是算术减号运算符。所以,0 - 35 是-35,当然,这不是一个有效的索引。我猜你想打印 0 到 35 的 范围,这可以通过 Arrays.toString 来完成:

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

【讨论】:

    【解决方案2】:

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

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

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

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

    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&lt;Integer&gt;.boxed())部分。
    4. 然后它将被转换为List&lt;Integer&gt;.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 大小估计,并不重要。

    【讨论】:

    • 你能告诉我一些其他的事情吗?我希望每行都以数字开头。但我希望这个数字在其他行中会有所不同,例如 1: \n 2: \n 3 等从 0 到 34 你能帮帮我吗?谢谢
    【解决方案3】:

    这是Java:

     a[0-35]
    

    其实意思是:

     a[-35]
    

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

    顺便说一句:考虑一下你的 switch 语句。

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

    case i:
      i++; 
    

    ?

    【讨论】:

    • 对不起,错字;我的意思是 -35(因为 0-35)。
    • 不客气 - 随时为正确答案投票并接受其中一个!
    • 我没有足够的声望来投票:/。无论如何,再次感谢你:)
    猜你喜欢
    • 1970-01-01
    • 2012-04-03
    • 2019-12-18
    • 1970-01-01
    • 2014-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多