8

I came across this helpful link with code which works perfectly when updated to hit against my web server. I can do absolutely everything.

Now, the only thing I do not fully understand is the Class.forName().

Why is this being used? Can this be done differently? Is this a work around for something else? Adding a reference? Creating a class as implementing/extending another one?

I want to fully understand what is going on, but this is in my way.

Thank you

jason m
  • 6,519
  • 20
  • 69
  • 122

4 Answers4

11

That code is forcing the class representing the MySQL driver to load and initialize. In Java, a class is not loaded unless it is necessary that the class gets loaded. Since JDBC code usually never directly references the driver, it wouldn't get loaded without Class.forName (or some other equivalent alternatives).

Note that it is necessary to both load and initialize the class, which are 2 different things.

Also, note that it is not necessary to call .newInstance() -- the static initializer of the Driver already registers itself as a JDBC driver.

Finally, note that with the Service Loader API it is usually not necessary to call Class.forName() to load the driver: it can be loaded automatically.

Bruno Reis
  • 37,201
  • 11
  • 119
  • 156
  • So this could be called consecutively on multiple classes representing drivers within my code without consequence I assume? But why do it this way? I suppose that is my real question. Is there not a more permanent (adding reference in the project etc) way to do this? – jason m Oct 17 '12 at 11:21
  • 1
    You must add a reference to the library for this to work. This is done this way in order to decouple the driver from your code, since it is assumed that you might want to replace databases and drivers later on. – Bruno Reis Oct 17 '12 at 11:23
  • For more info on class loading/initializing, check [this answer](http://stackoverflow.com/questions/8100376/class-forname-vs-classloader-loadclass-which-to-use-for-dynamic-loading/8100407#8100407) – Bruno Reis Oct 17 '12 at 11:24
  • Just to add that `.newInstance()` is actually needed, because some JDBC `Driver`s do not follow the specs, and do not register themselves during static initialization, but during instantiation. About the fact that "it is usually not necessary to call Class.forName": it is not necessary if you are using JDBC 4 or 4.1, et the `Driver` vendor did its job correctly. It is necessary if you are using JDBC3, or the vendor did not provide the class name of the `Driver` in `META-INF/services/java.sql.Driver`. – FBB Oct 10 '13 at 11:08
7

Class.forName(className) loads the class with the specified className.

JDBC drivers are loaded this way to avoid having to have a compile-time dependency on a specific JDBC driver. The idea is that you use Java's JDBC API (the classes and interfaces defined in the packages java.sql and javax.sql) without having to refer directly to a particular JDBC driver.

When you let Java load the driver class with the forName call, the driver will register itself so that it can be used.

Note that for most JDBC drivers it's unnecessary to explicitly create a new instance of the driver class; you can leave off the .newInstance() call.

Note that since JDBC version 4.0, the Class.forName() call isn't necessary anymore - the process to discover drivers has been improved, JDBC can load them automatically.

Jesper
  • 202,709
  • 46
  • 318
  • 350
5

All JDBC Drivers have a static block that registers itself with DriverManager and DriverManager has static an initializer only.

The MySQL JDBC Driver has a static initializer looks like this:

static {
    try {
        java.sql.DriverManager.registerDriver(new Driver());
    } catch (SQLException E) {
        throw new RuntimeException("Can't register driver!");
    }
}

JVM executes the static block and the Driver registers itself with the DriverManager. You need a database connection to manipulate the database. In order to create the connection to the database, the DriverManager class has to know which database driver you want to use. It does that by iterating over the array (internally a Vector) of drivers that have registered with it and calls the acceptsURL(url) method on each driver in the array, effectively asking the driver to tell it whether or not it can handle the JDBC URL.

Ta Duy Anh
  • 1,478
  • 9
  • 16
0

You can use for example:

import com.mysql.jdbc.Driver;

public class MyClass {
   //[...]
   public void myMethod() {
        Class<Driver> clz = Driver.class;
        Driver driver = clz.newInstance();
   }
}

But this is not so flexible; you can, for example, read the name "com.mysql.jdbc.Driver" from a config file. Maybe you want to user other driver (from Oracle) and you do not want to change the code; in the way presented above, this is not possible, so the proper approach is with Class.forName(name).

Random42
  • 8,989
  • 6
  • 55
  • 86