Рассмотрите эту пару Throwable
:
IllegalAccessException
extends Exception
Брошенный, когда приложение пытается отражающим образом создать экземпляр (кроме массива), установите или получите поле или вызовите метод, но в настоящее время метод выполнения не имеет доступа к определению указанного класса, поля, метода или конструктора.
IllegalAccessError
ext IncompatibleClassChangeError ext LinkageError ext Error
Брошенный, если приложение пытается получить доступ или изменить поле или назвать метод, к которому оно не имеет доступа.
Обычно, эта ошибка фиксируется компилятором; эта ошибка может только произойти во время выполнения, если определение класса несовместимо изменилось.
XXXError
и XXXException
комбинация? Как пары связаны друг с другом?try
кому: catch
один в Exception/Error
пара, должен Вы также catch
другой?Может ли кто-нибудь привести пример кода, в котором каждый из них будет выброшен?
Исключение IllegalAccessException
выбрасывается, когда вы пытаетесь использовать отражение для вызова метода или чтения или записи поля, которое запрещено правилами видимости Java.
Ошибка IllegalAccessError
не может быть вызвана последовательно скомпилированным кодом Java. Она возникает, когда, например, вы загружаете класс, который пытается вызвать метод или прочитать или записать поле в другом классе, что запрещено правилами видимости Java. Это то, что компилятор обычно предотвращает, поэтому это означает, что с классами что-то серьезно не так. В любом случае, это считается "ошибкой", т.е. невосстановимой, и загрузчик классов откажется загружать класс(ы)-нарушитель(и).
Означает ли сходство в названии связь между этими двумя понятиями, или это просто чистое совпадение?
Между этими двумя понятиями существует явная связь. Разница заключается в обстоятельствах, при которых они возникают.
Существуют ли другие пары XXXError и XXXException? Как эти пары связаны друг с другом?
Проехали. Проверьте javadocs.
Если вы явно пытаетесь поймать одно из исключений в паре Exception/Error, должны ли вы поймать и второе?
Скорее всего, нет. XXXError и XXXException обычно возникают в разных обстоятельствах. (Это, конечно, относится к отражающим и загрузчикам классов.)
Кроме того, как правило, вы не должны пытаться поймать и восстановить подтипы Error
. Весь смысл разделения Error
и Exception
в том, чтобы различать невосстанавливаемые и (потенциально) восстанавливаемые исключения.
В данном случае обычное приложение ничего не может сделать для восстановления после IllegalAccessError
. Если вы попытаетесь повторить операцию загрузчика классов, вызвавшую проблему, она просто повторится.
Описание уже объясняет часть этого: Исключение
возникает, когда вы используете отражение для доступа к полю или вызываете метод, который недоступен; Ошибка
возникает, когда вы делаете это напрямую (и по какой-то причине у компилятора не было возможности поймать это - например, когда у вас есть старая версия файла класса, в котором поле или метод, который вы пытаетесь использовать, является приватным).
Ошибка Ошибка
обычно указывает на то, что что-то действительно не так - почти наверняка в программе есть ошибка. Вы никогда не должны пытаться поймать Error
. Если вы ловите XXXException
, то нет никаких причин для того, чтобы ловить XXXError
. В документации к Error
говорится:
Error - это подкласс Throwable, который указывает на серьезные проблемы, которые разумное приложение не должно пытаться поймать. Большинство таких ошибок - это ненормальные условия. Ошибка ThreadDeath, хотя и является "нормальным" состоянием, также является подклассом Error, потому что большинство приложений не должны пытаться ее поймать.
Метод не обязан объявлять в своем выражении throws любые подклассы Error, которые могут быть выброшены во время выполнения метода, но не пойманы, поскольку эти ошибки являются аномальными условиями, которые никогда не должны возникать.
Пример генерации IllegalAccessException
: Через отражение найдите закрытый метод в классе и попытайтесь вызвать его.
Пример для генерации IllegalAccessError
: Создайте два класса и сохраните их в двух исходных файлах A.java
и B.java
. В классе A
создайте публичный метод, а в классе B
вызовите этот метод. Скомпилируйте исходные файлы. Теперь отредактируйте A.java
и сделайте метод приватным, и перекомпилируйте только A.java
(не B.java
). Теперь попробуйте запустить снова; B
попытается вызвать метод и выбросит IllegalAccessError
.
Есть и другие пары XXXException
/ XXXError
, которые кажутся связанными, но они не всегда имеют точно совпадающие имена; например, ClassNotFoundException
/ NoClassDefFoundError
.
В java.lang
есть несколько пар «Исключение / Ошибка», и все следующие варианты относятся к отражающему и прямому использованию:
IllegalAccessException / IllegalAccessError
InstantiationException / InstantiationError
ClassNotFoundException / NoClassDefFoundError
NoSuchFieldException / NoSuchFieldError
NoSuchMethodException / NoSuchMethodError
Другие примеры:
java.awt.AWTException / java.awt.AWTError
java.io.IOException / java.io.IOError
До сих пор я не знал, что эти две ошибки существуют, и что на них нет ссылок из других классов в Javadoc (1.6). Так что я не знаю, брошены ли они и когда.