简体   繁体   English

数组索引超出范围

[英]Array Index out of bounds

This is what I'm trying to do: I'm reading a file in from the command line. 这就是我要执行的操作:我正在从命令行读取文件。 The file contains a list of data,below this paragraph is what it looks like. 该文件包含一个数据列表,此段下面是它的样子。 The problem I'm having is with the if statements. 我遇到的问题是if语句。

import java.util.*;
import java.io.*;

public class VehicleTest {
    public static void main(String[] args) throws FileNotFoundException {
        String vehicle = "vehicle";
        String car = "car";
        String americanCar = "american car";
        String foreignCar = "foreign car";
        String truck = "truck";
        String bicycle = "bicycle";

        File file = new File(args[0]);
        Scanner input = new Scanner(file);

        String[] autos = new String[100];
        ArrayList allVehicles = new ArrayList();


        for (int i = 0; i < autos.length; i++) {
            autos[i] = input.nextLine();
        }

        int j = 0;
        int i = 0;

        while (i++ < autos.length) {
            if (vehicle.equalsIgnoreCase(autos[j++])) {
                Vehicle v = new Vehicle();
                v.setOwnerName(autos[j]);
                allVehicles.add(v);
            }else if(car.equalsIgnoreCase(autos[j++])){
                Car c = new Car();
                c.setOwnerName(autos[j]);
                allVehicles.add(c);
            }
        }

        for(Object a: allVehicles){
            System.out.println(a);
        }
    }
}

In pseudo code this would be: 用伪代码可以是:

while i is less than the length of the string  array  
 if you see the word vehicle create a new vehicle object and add it to the arrayList.  
 if you see the word car create a new car object and add it to the arrayList.  
.....

The problems is that I get an arrayOutOfBounds exception with the code I'm using. 问题是我使用的代码出现了arrayOutOfBounds异常。

I understand that j++ is what is wrong, but how else am I supposed to iterate through the string array so that I can read each line and create the appropriate objects? 我知道j ++出了什么问题,但是我还应该如何遍历字符串数组,以便可以读取每一行并创建适当的对象? I'm at a loss as to what to do. 我不知所措。 I need some help. 我需要协助。

foreign car  
aMarioy  
Mario's house  
(777) 777-7777  
gmario@mario.com  
false  
black  
Italy  
4415.91  

truck  
aDougy  
Doug's house  
(123) 456-7890  
hdoug@doug.com  
30  
61234.56  
8/10/2003  

vehicle  
aRobby  
Rob's house  
(987) 654-3210  
irob@rob.com  

bicycle  
bTommy  
Tom's house  
(246) 810-1214  
jtom@tom.com  
7  

truck  
bGeorge  
George's house  
(666) 666-6666  
kgeorge@george.com  
25  
51234.56  
12/4/2004  

vehicle  
bTim  
Tim's house  
(111) 111-1111  
tim@tim.com  

bicycle  
bJim  
Jim's house  
(555) 555-5555  
Ajim@jim.com  
5  

american car  
bJohn  
John's house  
(888) 888-8888  
Bjohn@john.com  
true  
green  
false  
true  

car  
cKen  
Ken's house  
(999) 999-9999  
Cken@ken.com  
false  
orange  

foreign car  
cMario  
Mario's house  
(777) 777-7777  
Dmario@mario.com  
false  
black  
Italy  
4415.91  


american car  
gSam  
Sam's house  
(333) 333-3333  
Hsam@sam.com  
false  
blue  
true  
false  

A couple of problems: 几个问题:

  • You're incrementing j in both "if" tests. 您在两个“ if”测试中都将j递增。 I haven't checked to be certain (it's quite convoluted code, to be honest) but if you make sure that you only increment j when you've found a match, that will help. 我尚未确定(老实说,这是很复杂的代码),但是如果您确保只在找到匹配项时才递增j,那会有所帮助。
  • Your test using i basically means it will try to read as many vehicles as there are lines in the file, rather than stopping when you've reached the end of the file. 使用i测试基本上意味着它将尝试读取文件中包含行数的所有车辆,而不是在到达文件末尾时停止读取。 Basically you don't need i here. 基本上,您在这里不需要i

Here's one changed version: 这是一个更改的版本:

    while (j < autos.length) {
        if (vehicle.equalsIgnoreCase(autos[j])) {
            j++;
            Vehicle v = new Vehicle();
            v.setOwnerName(autos[j++]);
            allVehicles.add(v);
        } else if(car.equalsIgnoreCase(autos[j])){
            j++;
            Car c = new Car();
            c.setOwnerName(autos[j++]);
            allVehicles.add(c);
        }
    }

It would be slightly cleaner to extract the type once though - then you can do the comparisons separately: 一次提取类型会更清洁-然后您可以分别进行比较:

    while (j < autos.length) {
        String type = autos[j++];
        if (vehicle.equalsIgnoreCase(type)) {
            Vehicle v = new Vehicle();
            v.setOwnerName(autos[j++]);
            allVehicles.add(v);
        } else if(car.equalsIgnoreCase(type)){
            Car c = new Car();
            c.setOwnerName(autos[j++]);
            allVehicles.add(c);
        }
    }

It's still not quite how I'd do it, but it's closer... 它仍然不是我要怎么做,但距离更近了...

My next step would be to use the scanner more appropriately: 我的下一步是更适当地使用扫描仪:

while (scanner.hasNext()) {
    String type = scanner.nextLine();
    if (type.equalsIgnoreCase("vehicle")) {
        allVehicles.add(new Vehicle(scanner));
    } else if (type.equalsIgnoreCase("car")) {
        allVehicles.add(new Car(scanner));
    }
    // ...
}

Then make the constructor for Vehicle, Car etc do the parsing directly from the scanner. 然后,使Vehicle,Car等的构造函数直接从扫描仪进行解析。

The next step would be to separate out the construction from the iteration. 下一步将是从迭代中分离出构造。 Introduce a new method: 介绍一种新方法:

// Use a base type in real code
private static Object parseNextVehicle(Scanner scanner) {
    String type = scanner.nextLine();
    if (type.equalsIgnoreCase("vehicle")) {
        return new Vehicle(scanner);
    } else if (type.equalsIgnoreCase("car")) {
        return new Car(scanner);
    }
    // ... throw an exception indicating an unknown vehicle type
}

// ... and then in the main method, use it like this:
while (scanner.hasNextLine()) {
    allVehicles.add(parseNextVehicle(scanner));
}

Every line that does not equal “vehicle” will (incorrectly) increment j so approximately after line 50 you will get the exception. 每行不等于“车辆”的行都会(错误地)使j递增,因此大约在第50行之后,您将获得异常。

There are multiple solutions to this: 有多种解决方案:

  • Increment j only once per loop. 每个循环仅将j递增一次。
  • Read the lines into another ArrayList . 将这些行读入另一个ArrayList
  • Don't read the lines into a data structure but process them as they are being read. 不要将行读入数据结构中,而应在读取时对其进行处理。 This way you are more independent of the size of your data. 这样,您将更加独立于数据大小。

Don't use j++ in the subscript; 不要在下标中使用j ++。 increment it once after the entire loop, rather than once or twice depending on which condition holds. 在整个循环后将其递增一次,而不是一次或两次,具体取决于哪种条件成立。

Probably better to do this: 这样做可能更好:

  • replace all your in-line increments (x++) with increment statements (x = x + 1) 将所有内联增量(x ++)替换为增量语句(x = x + 1)
  • figure out where they need to go to make the code do what you want 弄清楚他们需要去使代码执行您想要的操作的地方
  • turn them back to inline pre/post increments once you've gotten it working, if it seems appropriate 如果可行,将它们恢复为内联前/后增量

Put your increments and decrements in their own statement. 将增量和减量放在自己的语句中。 This will make the code easier to understand in most cases. 在大多数情况下,这将使代码更易于理解。

In your case, j++ is called twice if the first if fails. 在您的情况下,如果第一个if失败, j++被调用两次。 This is probably not what you want. 这可能不是您想要的。

I would convert your while loop into a for loop, like so: 我会将您的while循环转换为for循环,如下所示:

for (int i = 0, j = 0; i < autos.length; ++i, ++j) {
    if (vehicle.equalsIgnoreCase(autos[j])) {
        // ...

If i == j always, just use the same variable for both. 如果总是i == j ,则对两者都使用相同的变量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM