TL;DR
It’s not necessary to use Class.forName(String)
from Java 6, but doing so can still make your program refuse to boot if the driver is not in the classpath.
There is no need, and never has been, to use newInstance()
in that case. It serves absolutely nothing.
You can import and instantiate the driver directly if you want without problems.
Follow the detailed explanations:
The Class.forName(String)
is really necessary?
I’ll copy an excerpt of my other answer:
The driver boot process, using the Class.forName
is no longer required in the latest versions of Java. However, in doing so, you immediately denounce the presence of eventual classpath errors. Also, it only needs to be done once, while loading the program, and if it fails, the program is hopelessly broken. Therefore, this process can be kept in a static boot block.
This mechanism was responsible for ensuring that the driver class was loaded. Once loaded, the class performs its own registration as an SQL driver and is recognized by the class DriverManager
as such. From Java 6, you no longer need to use it.
A little bit of Reflection
For all classes loaded in the JVM, there is a class object java.lang.Class
corresponding. To get yourself a class from its name, you can use the method Class.forName(String)
.
The newInstance()
, is the method responsible for calling the constructor without parameters of a given class from the object Class
corresponding. Once it invokes the constructor, it naturally returns the created instance. With this, it is possible to create instances of classes from the object Class
.
Note that starting with Java 9, this method has become obsolete because it does not behave well in case the constructor throws an exception. The alternative is to trade newInstance()
for getDeclaredConstructor().newInstance()
.
The class ServiceLoader
With the advent of ServiceLoader
in Java 6, the explicit use of Class.forName(String)
for this case became unnecessary, as the ServiceLoader
is the mechanism that allows automatically enumerating services within Jars that implements a certain interface and it is this mechanism that drivers use to enumerate themselves without the programmer having to worry about it.
For example, if you open your mysql-connector-java-5.1.36.jar
as if it were a ZIP file, you will find a file called java.sql.Driver
inside a folder called META-INF/services
. Here is the contents of this file:
com.mysql.jdbc.Driver
com.mysql.fabric.jdbc.FabricMySQLDriver
When the ServiceLoader
for searching for interface implementations java.sql.Driver
, he will search the archive META-INF/services/java.sql.Driver
within each JAR, and in each JAR where this file is found, it will read a list with the name of the implementations. Then the ServiceLoader
going load each of these classes and then, as you carry them,
call the method newInstance()
, keeping the instances produced in a Map
.
However, how the ServiceLoader
is used internally by the class DriverManager
, you do not need to interact directly with it (nor need to know it exists) and no longer need to Class.forName(String)
manually. The only thing you need to do is to use the DriverManager
directly:
Connection con = DriverManager.getConnection(url, usuario, senha);
What the class of Driver
does after all?
Let’s take a look at class source code com.mysql.jdbc.Driver
:
package com.mysql.jdbc;
import java.sql.SQLException;
/**
* The Java SQL framework allows for multiple database drivers. Each driver should supply a class that implements the Driver interface
*
* <p>
* The DriverManager will try to load as many drivers as it can find and then for any given connection request, it will ask each driver in turn to try to
* connect to the target URL.
*
* <p>
* It is strongly recommended that each Driver class should be small and standalone so that the Driver class can be loaded and queried without bringing in vast
* quantities of supporting code.
*
* <p>
* When a Driver class is loaded, it should create an instance of itself and register it with the DriverManager. This means that a user can load and register a
* driver by doing Class.forName("foo.bah.Driver")
*/
public class Driver extends NonRegisteringDriver implements java.sql.Driver {
//
// Register ourselves with the DriverManager
//
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
/**
* Construct a new driver and register it with DriverManager
*
* @throws SQLException
* if a database error occurs.
*/
public Driver() throws SQLException {
// Required for Class.forName().newInstance()
}
}
Note that there is a static boot block that instantiates the class and registers it in the DriverManager
. Thus, when the class is loaded, the required driver instance is already created. That is, when a Class.forName(String)
is executed (either by you or indirectly by ServiceLoader
), she will be instantiated.
I can call the newInstance()
even so?
If you want to use the Class.forName(String)
even so, by calling the newInstance()
, you will create another instance that will not be registered on DriverManager
and by not assigning it to anywhere, it will soon be discarded by the garbage collector. That is, the explicit call to newInstance()
is totally useless and unnecessary.
However, having multiple driver instances is not harmful. In fact, one is registered in DriverManager
by the static initializer and a second instance is created by ServiceLoader
. If you use the newInstance()
, will create a third instance as well (even more if you assign it to some variable and use it later).
It would be expected that the fact that there is more than one instance of the driver could cause problems, but it does not result due to how it is implemented. If you look at source code of the superclass of com.mysql.jdbc.Driver
, which is the class com.mysql.jdbc.NonRegisteringDriver
, you will see that all fields are static and shared by any instances that may exist. Therefore, if all instances share the same state and do not maintain any state in themselves, they all have the same behavior and operate on the same data.
And if I import the driver directly?
By importing the driver directly, if you can guarantee that your code will load it, its static initializer will run and it will register on DriverManager
.
Use a com.mysql.jdbc.Driver.class
in the middle of the code is not enough to ensure the loading of the class. But, if you use one of these things, then it works:
Class<?> x = com.mysql.jdbc.Driver.class;
Or else:
new com.mysql.jdbc.Driver();
That is, since you remember that there may be several equivalent driver instances out there, you can do it yes and there will be no problem.
This is no longer necessary since java 1.6. Previously it was necessary for java to find the correct driver. But after the version cited, the compiler itself already looks for the most suitable driver and if not, throws exception.
– user28595
Related: java.lang.Runtimeexception: java.lang.Classnotfoundexception: org.postgresql.Driver
– user28595
@Almost Articuno. It’s not the compiler that does it. It’s the class
DriverManager
running time. The compiler itself does not want to know if the required class exists or not.– Victor Stafusa