ArrayIndexOutOfBoundsException False?

问题描述:

backgroundTiles = new Tile[width][height]; 
foregroundTiles = new Tile[width][height]; 


for(int i = 0 ; i < width*height; i++){ 
      int input = in.read(); 

      if(input == 13 || input == 10){ 
       i--; 
       continue; 
      } 

      if(input == 32){ 
       continue; 
      } 

      int x = i%width; 
      int y = i/height; 


      System.out.println(x + " : " + level.foregroundTiles.length); 
      level.foregroundTiles[x][y] = Tile.tiles[input-48]; 
} 

该代码在不应该引发ArrayIndexOutOfBoundsException时抛出该异常。即使这个例外本身也说明它不应该被抛出。ArrayIndexOutOfBoundsException False?

java.lang.ArrayIndexOutOfBoundsException: 5 
    at com.vobis.avp.io.LevelLoader.readLevel(LevelLoader.java:51) 
    at com.vobis.avp.io.LevelLoader.<clinit>(LevelLoader.java:12) 
    at com.vobis.avp.AVPGame.<init>(AVPGame.java:48) 
    at com.vobis.avp.AVPStartUp.main(AVPStartUp.java:6) 

但是,这只是例外,我打印出来,随后的level.foregroundTiles.length的价值,这显然是10,5 : 10x当前值之前。那么当我清楚地访问数组边界内的索引时,怎么会发生这种异常呢?

的错误是其中Y

+4

'y'和'Tile.tiles [输入-48]'也出界外。检查他们。 – fluidsonic 2014-10-10 14:39:42

+0

什么是AVPGame第51行?它会触发NullPointerException – ToYonos 2014-10-10 14:41:21

+2

问问自己:Java数组索引中存在一个错误的几率是多少? – 2014-10-10 14:53:01

你可以很容易地创建一个嵌套的循环,以避免所有你正在做的靠不住数学。明确的意图是关键。

for(int x = 0; x < width; x++) { 
    for(int y = 0; y < height; y++) { 
     // code 
    } 
} 

这也意味着你可能摆脱Tile.tiles[input-48];,其中减去一些数量input任意48(这最好是大于或等于48,或者你会得到一个AIOOBE)。

+0

但是如果'input == 13 ||输入== 10'?我从循环中减去什么以保持一致? – 2014-10-10 18:13:34

+0

如果你使用两个循环,没有任何东西。这个循环会代替你的界限。 – Makoto 2014-10-10 18:14:47

+0

但是现在我的游戏世界里有'CR'或'NL'(换行符) – 2014-10-10 18:21:18

你的问题是,你不检查

level.foregroundTiles[x].length 

Tile.tiles.length 

在您访问,你还没有验证指标存在。 Makoto的建议是无效的。将y检查添加到循环将避免IndexOutOfBoundsException,但会导致无法访问数组的某些有效索引的逻辑错误;您在每次迭代中都没有访问第y个索引+1,您正在访问i/height处的索引。

你想要的东西的(你将需要重构,很明显)效果:

for(int i = 0, x = i%width, y = i/height; i < width*height && x < level.foregroundTiles.length && y < level.foregroundTiles[x].length; i++, x = i%width, y = i/height){ 
     int input = in.read(); 
     if (input-48 < 0 || input-48 >= Tile.tiles.length){ 
      //do some error handling 
      continue; //or break; 
     } 
     ....