В Java может ли Class.forName когда-либо возвращать значение null, или он всегда будет генерировать исключение ClassNotFoundException или NoClassDefFoundError, если класс не может быть обнаружен?




Поскольку значение null нигде не упоминается в документации по этому методу и поскольку не существует ситуации, в которой метод возвращал бы значение null вместо генерации исключения, я думаю, что довольно безопасно предположить, что это никогда не возвращает null.
Он не вызовет NoClassDefFoundError, но может вызвать исключение ClassNotFoundException.
Он уже выбрасывает ClassNotFoundException, было бы запутанно, если бы он использовал оба. NoClassDefFoundError генерируется виртуальной машиной, когда она не может найти класс в ходе своих обычных операций. ClassNotFoundException возникает, когда класс не может быть найден кодом, использующим отражение.
Это не совсем так. Class.forName выбрасывает NCDFE, см. Мой ответ ниже.
@Hermal: Нет, это не так; JVM бросает его в ваш пример, пытаясь разрешить класс из «нормальной» ссылки (не отраженной); это просто происходит через Class.forName (). Любой метод может увидеть прохождение NCDFError через него.
В документации Java говорится, что он вызовет исключение ClassNotFoundException, если класс не может быть найден, поэтому я бы сказал, что он никогда не возвращает значение null.
Что делать, если вы используете собственный загрузчик классов?
Затем пользовательский загрузчик классов нарушает контракт. Вам нужно будет решить, хотите ли вы кодировать эту непредвиденную ситуацию. Точно так же, если вы используете верхнюю часть среды выполнения AOP, перезапишите существующие классы, например загрузчик классов. :-)
@ Даррон: О каком контракте вы говорите?
@Hemal на Дарроне: вернуть ClassNotFoundException.
Не знаю, что мне не хватает. Вы имеете в виду то, что Class.forName throws CNFE? Но это не означает, что он не может возвращать null или что он не может генерировать другие непроверенные исключения.
Используя загрузчик классов по умолчанию, вы наверняка не получите нулей. Но, как говорит jdigital, вы можете подвергнуться любому количеству настраиваемых загрузчиков классов в зависимости от того, какую модель безопасности или другой тип прокси-загрузчика вы можете использовать (намеренно или иным образом).
Черт возьми, даже forName может принимать ClassLoader в качестве параметра ... :)
Пико
Что ж, если вы используете "плохой" загрузчик пользовательских классов, вы можете получить Корову в этом отношении !! :)
Этот ответ будет точным только для загрузчика классов, который нарушает документированный контракт - я бы не стал для этого кодировать.
@Dan Dyer ошибается, Class.forName может выбрасывает NoClassDefFoundError, если класс, который он пытается, получает ошибку ClassNotFoundException в своем статическом инициализаторе. Следующее unte
class Outer {
public static final void main(final String[] args) throws Exception{
Class.forName("Inner");
}
}
Если вы скомпилируете и запустите это в каталоге без других файлов, вы получите ClassNotFoundException: Inner
Теперь добавьте следующее в тот же каталог, скомпилируйте все и java Outer один раз, чтобы убедиться, что он работает нормально.
class Inner {
static Inner2 _i2 = new Inner2();
}
class Inner2 {}
Наконец, удалите Inner2.class и перезапустите Outer, вы будут получите NoClassDefFoundError: Inner2, caused by ClassNotFoundException: Inner2
Нет, это не так; JVM бросает его в ваш пример, пытаясь разрешить класс из «нормальной» ссылки (не отраженной); это просто происходит через Class.forName (). Любой метод может увидеть прохождение NCDFError через него.
Хм. Да, я понимаю, о чем вы говорите. Это как сказать, что Class.forName выбрасывает NPE или OOME, потому что загружаемый класс выбрасывает его в свой клинит.
«@ Дэн Дайер ошибается» - не лучший способ ответить на вопрос Фила.
Да, это должен был быть комментарий к ответу Дэна. Но я хотел отформатировать код, поэтому использовал отдельную запись. Конечно, я ошибался, говоря, что Дэн неправ. Посмотрите на преимущество: в качестве бонуса я получил несколько голосов против :-)
Почему он не выдаст ошибку NCDFError?