Поиск и устранение неисправностей (Учебные руководства Java™> API Reflection> Массивы и Перечислимые типы)


След: API Reflection
Урок: Массивы и Перечислимые типы
Раздел: Массивы
Поиск и устранение неисправностей
Домашняя страница > API Reflection > Массивы и Перечислимые типы

Поиск и устранение неисправностей

Следующие примеры показывают типичные ошибки, которые могут произойти, работая на массивах.

IllegalArgumentException из-за Необратимых Типов

ArrayTroubleAgain пример генерирует IllegalArgumentException. Array.setInt() вызывается, чтобы установить компонент, который имеет ссылочный тип Integer со значением типа примитива int. В неотражательном эквиваленте ary[0] = 1, компилятор преобразовал бы (или поле) значение 1 к ссылочному типу как new Integer(1) так, чтобы его проверка типа приняла оператор. При использовании отражения введите проверку, только происходит во времени выполнения, таким образом, нет никакой возможности к полю значения.


import java.lang.reflect.Array;
import static java.lang.System.err;

public class ArrayTroubleAgain {
    public static void main(String... args) {
	Integer[] ary = new Integer[2];
	try {
	    Array.setInt(ary, 0, 1);  // IllegalArgumentException

        // production code should handle these exceptions more gracefully
	} catch (IllegalArgumentException x) {
	    err.format("Unable to box%n");
	} catch (ArrayIndexOutOfBoundsException x) {
	    x.printStackTrace();
	}
    }
}
$ java ArrayTroubleAgain
Unable to box

Чтобы устранить это исключение, проблематичная строка должна быть заменена следующим вызовом Array.set(Object array, int index, Object value):

Array.set(ary, 0, new Integer(1));

Подсказка: При использовании отражения, чтобы установить или получить компонент массива, у компилятора нет возможности выполнить упаковку. Это может только преобразовать типы, которые связываются как описано спецификацией для Class.isAssignableFrom(). Пример, как ожидают, перестанет работать потому что isAssignableFrom() возвратится false в этом тесте, который может использоваться программно, чтобы проверить, возможно ли определенное преобразование:
Integer.class.isAssignableFrom(int.class) == false 

Точно так же автоматическое преобразование от примитивного до ссылочного типа также невозможно в отражении.

int.class.isAssignableFrom(Integer.class) == false

ArrayIndexOutOfBoundsException для Пустых Массивов

ArrayTrouble пример иллюстрирует ошибку, которая произойдет, если попытка будет предпринята, чтобы получить доступ к элементам массива нулевой длины:


import java.lang.reflect.Array;
import static java.lang.System.out;

public class ArrayTrouble {
    public static void main(String... args) {
        Object o = Array.newInstance(int.class, 0);
        int[] i = (int[])o;
        int[] j = new int[0];
        out.format("i.length = %d, j.length = %d, args.length = %d%n",
                   i.length, j.length, args.length);
        Array.getInt(o, 0);  // ArrayIndexOutOfBoundsException
    }
}
$ java ArrayTrouble
i.length = 0, j.length = 0, args.length = 0
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
        at java.lang.reflect.Array.getInt(Native Method)
        at ArrayTrouble.main(ArrayTrouble.java:11)

Подсказка: возможно иметь массивы без элементов (пустые массивы). Есть только несколько случаев в общем коде, где они замечаются, но они могут произойти в отражении непреднамеренно. Конечно, не возможно установить/получить значения пустого массива потому что ArrayIndexOutOfBoundsException будет брошен.

IllegalArgumentException, если Сужение Предпринимается

ArrayTroubleToo пример содержит код, который перестал работать, потому что это пытается, выполняют работу, которая могла потенциально потерять данные:


import java.lang.reflect.Array;
import static java.lang.System.out;

public class ArrayTroubleToo {
    public static void main(String... args) {
        Object o = new int[2];
        Array.setShort(o, 0, (short)2);  // widening, succeeds
        Array.setLong(o, 1, 2L);         // narrowing, fails
    }
}
$ java ArrayTroubleToo
Exception in thread "main" java.lang.IllegalArgumentException: argument type
  mismatch
        at java.lang.reflect.Array.setLong(Native Method)
        at ArrayTroubleToo.main(ArrayTroubleToo.java:9)

Подсказка: Array.set*() и Array.get*() методы выполнят автоматическое расширяющееся преобразование, но бросят IllegalArgumentException если сужающееся преобразование предпринимается. Для полного обсуждения расширения и сужения преобразований, см. Спецификацию языка Java, Java SE 7 Выпусков, разделы, Расширяющие Примитивное Преобразование и Сужающие Примитивное Преобразование соответственно.

Проблемы с примерами? Попытайтесь Компилировать и Выполнить Примеры: FAQ.
Жалобы? Поздравление? Предложения? Дайте нам свою обратную связь.

Предыдущая страница: Получение и Установка Массивов и Их Компонентов
Следующая страница: Перечислимые типы



Spec-Zone.ru - all specs in one place