Подтвердить что ты не робот

Как работает Class.forName()?

Я только что узнал о java.sql package. Он использует Class.forName() для динамической загрузки драйвера, который расширяет DriverManager. Затем мы получаем соединение с помощью метода DriverManager.getConnection().

Итак, как все работает?
Как класс DriverManager знает, как получить соединение, не используя имя класса фактического драйвера.

Также мы можем использовать Class.forName() для пользовательских приложений... если это объясняется примером, я буду очень рад.

4b9b3361

Ответ 1

Class.forName просто загружает класс, включая запуск его статических инициализаторов, например так:

class Foo {
    static {
        System.out.println("Foo initializing");
    }
}

public class Test {
    public static void main(String [] args) throws Exception {
        Class.forName("Foo");
    }
}

Все остальные процедуры, о которых вы говорите, относятся к JDBC. Драйвер, который реализует Driver, но не расширяет DriverManager просто регистрирует соответствующий экземпляр с помощью DriverManager.registerDriver. Затем, когда DriverManager необходимо найти драйвер для определенной строки соединения, он вызывает connect для каждого зарегистрированного драйвера по очереди, пока один из них не завершится успешно и не вернет ненулевое соединение.

Обратите внимание, что этот способ регистрации драйверов является довольно старомодным - посмотрите на документы для DriverManager для более современных способов получить DriverManager к источнику данных.

Ответ 2

Когда мы создаем instace класса с использованием нового оператора, он выполняет две вещи

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

Class.forName делает только первое. Он загружает класс в память и возвращает эту ссылку как экземпляр класса. Если мы хотим создать экземпляр, тогда мы можем вызвать метод newInstance этого класса. который будет вызывать конструктор по умолчанию (без конструктора аргументов). Обратите внимание: если конструктор по умолчанию недоступен, то метод newInstance будет вызывать IllegalAccessException. и если класс является абстрактным классом или интерфейсом или у него нет конструктора по умолчанию, тогда он будет бросать InstantiationException. Если какое-либо исключение возникает при разрешении этого класса, оно будет бросать ExceptionInInitializerError.

Если конструктор по умолчанию не определен, тогда мы должны вызвать конструктор defiend с использованием API отражения.

Но главным преимуществом класса Class.forName является то, что оно может принимать имя класса как аргумент String. Таким образом, мы можем передавать имя класса динамически. Но если мы создадим экземпляр класса с использованием нового оператора, имя класса не может быть изменено динамически.

Class.forName() inturn вызовет метод loadClass вызывающего класса ClassLoader (ClassLoder класса, из которого вызывается Class.forName).

По умолчанию Class.forName() разрешает этот класс. что означает, инициализировать все статические переменные внутри этого класса. то же самое можно изменить с помощью перегруженного метода Class.forName(String name,boolean initialize,ClassLoader loader)

Основной причиной загрузки драйвера jdbc с помощью Class.forName() является то, что драйвер может динамически меняться. в статическом блоке все Драйверы создадут экземпляр самого себя и зарегистрируют этот класс с помощью DriverManager, используя метод DriverManager.registerDriver(). Поскольку Class.forName(String className) по умолчанию разрешает класс, он инициализирует статический инициализатор. Поэтому, когда мы называем Class.forName("com.sun.jdbc.odbc.JdbcOdbcDriver"), класс драйвера будет загружен, проинструктирован и зарегистрирован с помощью DriverManager

Итак, если вы используете новый оператор, вам нужно сделать следующее.
Код:

Driver drv = new com.sun.jdbc.odbc.JdbcOdbcDriver();
DriverManager.registerDriver(drv);

Ответ 3

Class.forName(..) загружает и инициализирует целевой класс. Это, в свою очередь, означает, что активируются блоки статического инициализатора (код, определенный в static { .. }.

Если вы посмотрите, например, на драйвер MySQL, в этом статическом блоке водитель регистрируется: DriverManager.registerDriver(new Driver());

Вы можете опустить Class.forName(..) и зарегистрировать драйвер самостоятельно, если вы можете "позволить себе" зависимость времени компиляции от драйвера MySQL.

Тем не менее, редко будет иметь смысл использовать Class.forName(..) для инициализации классов из вашего приложения, потому что зависимость от компиляции не является проблемой.

Также обратите внимание, что Class.forName(..) больше не требуется для JDBC с версии 4. Используя поставщик услуг, вы можете указать диспетчеру драйвера, что загрузить с помощью системного свойства.

Ответ 4

Причина, по которой Class.forName() часто упоминается в примерах SQL, заключается в том, что не было волшебства, чтобы сообщить JDBC DriverManager, как сопоставить URL JDBC, предоставленный реальному драйверу.

например. "mysql" должен сопоставляться с заданным классом MySQL "тонкие" карты с классом Oracle, "as400" сопоставляется с классом DB2/400.

Явным образом загружая класс, это позволило коду внутри класса регистрироваться при запуске DriverManager.

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