Разница между Class.forName() и .newInstance() в Java
Быстрый ответ
Применение метода Class.forName(String className)
дает возможность загрузить определенный класс, не создавая при этом его объект. Это можно сравнить со взглядом на витрину магазина: вы просто знакомитесь с классом, в процессе чего выполняются его статические блоки инициализации, если таковые присутствуют.
Метод Class.forName(String className).newInstance()
, в свою очередь, делает не только загрузку класса, но также и создает его новый экземпляр путем вызова конструктора без параметров. Этот вариант выглядит как полноценная покупка.
Советуемый подход (начиная с Java 9):
// Более продвинутый вариант
Object obj = Class.forName("com.example.MyClass")
.getDeclaredConstructor()
.newInstance();
Примечание: Метод .newInstance()
считается устаревшим, поэтому лучше применять вышеуказанный вариант, обеспечивающий удобное управление исключениями.
[AsideBanner]
Загрузка класса vs создание экземпляра
При вызове Class.forName()
инициируется процесс загрузки класса, включающий такие стадии как верификация, подготовка, разрешение и инициализация. Это особенно актуально для JDBC, поскольку именно таким образом происходит регистрация драйверов с помощью статических блоков инициализации.
Метод newInstance()
уже предполагает создание нового экземпляра класса. Это происходит путем вызова конструктора, не требующего аргументов.
Какой метод выбрать? Это зависит от контекста
Если вы планируете работать исключительно со статическими переменными и методами класса, и при этом хотите избежать лишних затрат на создание объекта, вам подойдет Class.forName()
.
С введением автоматической регистрации драйверов в JDBC 4.0 требование использовать Class.forName().newInstance()
для регистрации драйверов стало относиться к истории.
Обратите внимание
Очередное применение newInstance()
может привести к возникновению исключения, например, InstantiationException
, в случае если класс не содержит публичный конструктор без аргументов. К тому же может появиться IllegalAccessException
из-за наличия внутренних ограничений безопасности. В итоге намного правильнее использовать getDeclaredConstructor().newInstance()
, что способствует эффективному управлению исключениями.
Визуализация
Различие между Class.forName() и Class.forName().newInstance() удобно уместить в аналогию с прогулкой по магазину (🏬):
🏬 Шагаете по магазину: Class.forName("MyClass")
// Вы получаете карту расположения товаров класса 'MyClass'.
Вам предстоит из двух вариантов:
- Обзор сделки:
При отсутствии метода `.newInstance()`:
Вы осведомились о схеме 🗺️, но покупка так и осталась на месте.
// Вы узнали, где находятся товары класса MyClass, однако их не стали приобретать.
- Заключение сделки:
Путем использования `.newInstance()`:
Вы выходите из магазина, держа в руках покупку 🗺️🛍️.
// Вы не только обнаружили товары класса MyClass, но также приобрели новый экземпляр MyClass.
| Действие | Результат |
| --------------- | ---------------------------------- |
| .forName() | 🗺️ Ознакомились с "MyClass" |
| .newInstance() | 🛍️ Получен новый экземпляр "MyClass" |
// Путем применения .newInstance()
вы приобретаете новый экземпляр класса, готовый для использования.
Исследование устаревшей функциональности
Не смотря на то, что метод newInstance()
признается устаревшим, опытные разработчики понимают его значение, особенно в контексте поддержки устаревшего кода. Более современные подходы предлагают больше безопасности и выразительности для решения характерных ошибок.
Адаптация с Java
С развитием Java имплементация фабричных паттернов и внедрения зависимостей снизила значимость Class.forName().newInstance()
. В настоящее время мы стремимся к более структурированным и модулируемым решениям, таким как API загрузчик услуг или Spring BeanFactory.
Осознание производительности
Прежде чем глубоко увлекаться рефлексией, нужно помнить о высоких требованиях к производительности. Рефлексия, в отличие от статического создания экземпляров, требует больше ресурсов и времени, а также ограничивает вас проверками во время выполнения, вместо проверок на этапе компиляции, что может приводить к ошибкам.
Полезные материалы
- Class (Java SE 8 platform) – Официальная документация на
Class.forName()
по версии Java 8. - Class (Java SE 9 & JDK 9) – Аргументация удаления метода
Class.newInstance()
по документации Java 9. - Какова разница между "Class.forName()" и "Class.forName().newInstance()"? – Stack Overflow – Практические обсуждения и мнения.
- Почему метод Class.newInstance() считается "нежелательным как дурное обращение"? – Stack Overflow – Интерпретация, почему метод
Class.newInstance()
приобрел дурную славу. - Стоит ли только мгновение... – Детальное описание по
Class.forName()
от Baeldung. - Учебники | DigitalOcean – Разработка способности создавать объекты в Java, имеющая известность путем JournalDev.
- Java.lang.Class в Java | Часть 1 – GeeksforGeeks – Остовы класса Class в Java и задачи
Class.forName()
.