Java создает исключение ArrayIndexOutOfBoundsException при использовании обычного цикла if, но не при использовании расширенного цикла for. Зачем? - PullRequest
0 голосов
/ 06 июля 2018

Исходный код:

public class Main {
    String line;
    static List<String> currentProcesses = new ArrayList<>();


    public static void main(String[] args) {
        try {
            String line;
            Process p = Runtime.getRuntime().exec(System.getenv("windir") +"\\system32\\"+"tasklist.exe");
            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));

            while ((line = input.readLine()) != null) {
                if (!line.contains("System Idle Process")) {
                    System.out.println(line);

                    String[] splitLine = line.split(" ");               
                    if (!splitLine[0].contains("=") && !splitLine[0].equals("Image")) {
                        //this is the erroenous part of code
                        String[] refinedSplitLine = eliminateSpacebarCharacters(splitLine);

                        for (int i = 0; i<4; i++) {
                            System.out.println(refinedSplitLine[i]);
                        }
                        /*
                        for(String s:refinedSplitLine) {
                            System.out.println(s);
                        }
                        */

                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Eliminates spacebar characters from a file and returns a String array
     * @param line
     * @return
     */
    private static String[] eliminateSpacebarCharacters(String[] line) {    
        List<String> refinedList = new ArrayList<>();

        for (String s : line) {
            if (!s.equals("")) {
                refinedList.add(s);
            }
        }

        String[] refinedStringArray = new String[refinedList.size()];

        for(int i = 0; i < refinedStringArray.length; i++) {
            refinedStringArray[i] = refinedList.get(i);
        }

        System.out.println("Displaying refinedStringArray...");
        ArrayUtils.displayArray(refinedStringArray);

        return refinedStringArray;
    }
}

Моя программа выполняет следующие действия:

  • Получить доступ и прочитать (используя BufferedReader) все открытые в данный момент системные процессы. Каждый системный процесс представлен строкой, например (из-за форматирования очень много пробельных символов; первый элемент строки относится к так называемому имени изображения, второй к PID, третий к имени сеанса, четвертый к номеру сеанса и пятое - использование памяти этим процессом):

System 4 Services 0 2.608 K

  • Затем каждая строка разбивается на массив строк на основе символов пробела (String[] splitLine).
  • Затем каждый такой массив удаляется из пробельных символов, используя метод String[] eliminateSpacebarCharacters(String[] line). Этот массив строк без пробелов называется refinedSplitLine.
  • Ошибка при попытке доступа к элементам refinedSplitLine

Я пытался отобразить уточненный массив строк (без пробельных символов) внутри eliminateSpacebarCharacters с помощью следующих строк кода

System.out.println("Displaying refinedStringArray...");
ArrayUtils.displayArray(refinedStringArray);

//this is displayArray method in ArrayUtils class
public static void displayArray(String[] array) {
    int i = 0;
    for (String s:array) {
        System.out.print("[" + i + "]: " + s + " ");
        i++;
    }
}

И это отображает желаемый результат: [0]: WmiPrvSE.exe [1]: 23156 [2]: Services [3]: 0 [4]: 8.680 [5]: K, что означает, что массив, возвращаемый методом, заполнен элементами.

Теперь этот раздел кода демонстрирует возникновение такой ошибки. Если попытаться получить доступ к какому-либо элементу refinedSplitLine по его индексу в предложении if (!splitLine[0].contains("=") && !splitLine[0].equals("Image")), генерируется исключение. Почему?

if (!splitLine[0].contains("=") && !splitLine[0].equals("Image")) {
        String[] refinedSplitLine = eliminateSpacebarCharacters(splitLine);
        System.out.println(refinedSplitLine[0]);
}

Это выброшенное исключение:

Exception in thread "main" 
java.lang.ArrayIndexOutOfBoundsException: 0
at Main.main(Main.java:27) //this line refers to System.out.println above

Та же ошибка выдается при попытке использовать регулярный цикл for для доступа к элементам refinedSplitLine. Однако, если попытаться использовать расширенный цикл for, ошибка не выдается. Почему?

if (!splitLine[0].contains("=") && !splitLine[0].equals("Image")) {
                    String[] refinedSplitLine = eliminateSpacebarCharacters(splitLine);
                    //ArrayUtils.displayArray(refinedSplitLine);

                    for(String s:refinedSplitLine) {
                        System.out.println(s);
                    }

                    /*
                    for (int i = 0; i<4; i++) {
                        System.out.println(refinedSplitLine[i]);
                    }*/

RefinedSplitLine заполняется элементами, однако при попытке доступа к ним выдается сообщение об ошибке, как если бы в массиве не было элементов.

Спасибо за потраченное время.

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

Вы используете для цикла неправильно. Вы не можете быть уверены, что refinedSplitLine содержит элемент. Просто замените следующую петлю:

for (int i = 0; i<4; i++) {
    System.out.println(refinedSplitLine[i]);
}

С этим:

for (int i = 0; i<refinedSplitLine.length; i++) {
   System.out.println(refinedSplitLine[i]);
}

Для каждого работает нормально, потому что он перебирает все элементы массива, если он пустой, он просто ничего не печатает. Но обычный цикл в вашем случае пытается получить элемент из массива, индекс которого не существует, поэтому у вас есть исключение.

0 голосов
/ 06 июля 2018

java.lang.ArrayIndexOutOfBoundsException: 0 указывает на то, что вы обращаетесь к массиву нулевой длины, в котором все индексы выходят за пределы.

Цикл foreach просто пропустит его, поскольку видит, что элементов нет. Ваш другой цикл, похоже, ожидает 4 элемента.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...