我的程序因 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")
这是做什么的:
- 这会将
int[]
转换为 IntStream
(IntStream.of(a)
部分)。
- 让我们限制为仅获取前 36 个元素(因为您想要从 0 到 35 的元素)。这就是
.limit(36)
的作用。
- 然后
IntStream
将被转换为 Stream<Integer>
(.boxed()
)部分。
- 然后它会被转换成
List<Integer>
(.collect(Collectors.toList())
)部分。
- 然后它会被转换成一个
String
(.toString()
部分)。
- 由于
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);
}
}
新的改进答案:
为了显示行号,我认为Stream
s 方法行不通,否则会过于复杂。因此,让我们改用专门的方法:
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
大小估计,这不是重要的事情.
您好,我的程序无法 运行 和 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")
这是做什么的:
- 这会将
int[]
转换为IntStream
(IntStream.of(a)
部分)。 - 让我们限制为仅获取前 36 个元素(因为您想要从 0 到 35 的元素)。这就是
.limit(36)
的作用。 - 然后
IntStream
将被转换为Stream<Integer>
(.boxed()
)部分。 - 然后它会被转换成
List<Integer>
(.collect(Collectors.toList())
)部分。 - 然后它会被转换成一个
String
(.toString()
部分)。 - 由于
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);
}
}
新的改进答案:
为了显示行号,我认为Stream
s 方法行不通,否则会过于复杂。因此,让我们改用专门的方法:
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
大小估计,这不是重要的事情.