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

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

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

IllegalArgumentException, Пытаясь Инстанцировать Перечислимого Типа

Как был упомянут, инстанцирование перечислимых типов запрещается. EnumTrouble пример делает попытку этого.


import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import static java.lang.System.out;

enum Charge {
    POSITIVE, NEGATIVE, NEUTRAL;
    Charge() {
	out.format("under construction%n");
    }
}

public class EnumTrouble {

    public static void main(String... args) {
	try {
	    Class<?> c = Charge.class;

 	    Constructor[] ctors = c.getDeclaredConstructors();
 	    for (Constructor ctor : ctors) {
		out.format("Constructor: %s%n",  ctor.toGenericString());
 		ctor.setAccessible(true);
 		ctor.newInstance();
 	    }

        // production code should handle these exceptions more gracefully
	} catch (InstantiationException x) {
	    x.printStackTrace();
	} catch (IllegalAccessException x) {
	    x.printStackTrace();
	} catch (InvocationTargetException x) {
	    x.printStackTrace();
	}
    }
}
$ java EnumTrouble
Constructor: private Charge()
Exception in thread "main" java.lang.IllegalArgumentException: Cannot
  reflectively create enum objects
        at java.lang.reflect.Constructor.newInstance(Constructor.java:511)
        at EnumTrouble.main(EnumTrouble.java:22)

Подсказка: Это - ошибка времени компиляции, чтобы попытаться явно инстанцировать перечисления, потому что это препятствовало бы тому, чтобы определенные перечислимые константы были уникальны. Это ограничение также осуществляется в отражающем коде. Код, который пытается инстанцировать классов, используя их конструкторов по умолчанию, должен вызвать Class.isEnum() сначала, чтобы определить, является ли class перечислением.

IllegalArgumentException, Устанавливая Поле с Несовместимым Перечислимым Типом

Поля, хранящие перечисления, устанавливаются с соответствующим перечислимым типом. (Фактически, поля любого типа должны быть установлены с совместимыми типами.) EnumTroubleToo пример производит ожидаемую ошибку.


import java.lang.reflect.Field;

enum E0 { A, B }
enum E1 { A, B }

class ETest {
    private E0 fld = E0.A;
}

public class EnumTroubleToo {
    public static void main(String... args) {
	try {
	    ETest test = new ETest();
	    Field f = test.getClass().getDeclaredField("fld");
	    f.setAccessible(true);
 	    f.set(test, E1.A);  // IllegalArgumentException

        // production code should handle these exceptions more gracefully
	} catch (NoSuchFieldException x) {
	    x.printStackTrace();
	} catch (IllegalAccessException x) {
	    x.printStackTrace();
	}
    }
}
$ java EnumTroubleToo
Exception in thread "main" java.lang.IllegalArgumentException: Can not set E0
  field ETest.fld to E1
        at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException
          (UnsafeFieldAccessorImpl.java:146)
        at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException
          (UnsafeFieldAccessorImpl.java:150)
        at sun.reflect.UnsafeObjectFieldAccessorImpl.set
          (UnsafeObjectFieldAccessorImpl.java:63)
        at java.lang.reflect.Field.set(Field.java:657)
        at EnumTroubleToo.main(EnumTroubleToo.java:16)

Подсказка: Строго говоря, любая попытка установить поле типа X к значению типа Y может только успешно выполниться, если следующий оператор содержит:
X.class.isAssignableFrom(Y.class) == true
Код мог быть изменен, чтобы выполнить следующий тест, чтобы проверить, являются ли типы совместимыми:
if (f.getType().isAssignableFrom(E0.class))
    // compatible
else
    // expect IllegalArgumentException


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

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