Wednesday, 22 June 2016

[Java] What is difference between Class.forName() and Class.forName().newInstance()

In JavaDoc, calling Class.forName( String) returns the Class object associated with the class or interface with the given string name.
On the other hand, calling Class.forName( String).newInstance() creates a new instance of the class represented by this Class object. The class is instantiated as if by a new expression with an empty argument list.
In other words, Class.forName( String CLASS_NAME) is equivalent to new CLASS_NAME()
(Referenced by http://stackoverflow.com/questions/2092659/what-is-the-difference-between-class-forname-and-class-forname-newinstanc)


Class.forName( String) is not create instance, but call static block in class. On the other hand, newInstance() creates instance. The result of below code will make you more understandable.

Class pe.dorbae.test.Driver
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package pe.dorbae.test;

/*
 * ************************************************************************************
 *
 * Driver.java
 * 
 * ************************************************************************************
 * 
 * @version 1.0.00 2016-06-21 dorbae Initialize
 * @since 2016-06-21
 * @author dorbae
 * 
 * ************************************************************************************
 */
public class Driver {
 
 static {
  System.out.println( "Static Block");
 }

 public Driver() {
  System.out.println( "Constructure");
  
 }
 
 public void test() {
  System.out.println( "test");
 }
 
}


Calling Class.forName( String) Code and Result
1
2
3
4
5
6
public class Test {
 public static void main(String[] args) throws Exception {
  Class.forName( "pe.dorbae.test.Driver"); // equivalent to Class.forName( "pe.dorbae.test.Driver", true, this.getClass().getClassLoader())
  
 }
}




Calling Class.forName( String, false, ClassLoader) Code and Result
1
2
3
4
5
6
public class Test {
 public static void main(String[] args) throws Exception {
  Class.forName( "pe.dorbae.test.Driver", false, Thread.currentThread().getContextClassLoader());
  
 }
}



Calling Class.forName( String).newInstance()
1
2
3
4
5
6
public class Test {
 public static void main(String[] args) throws Exception {
  Class.forName( "pe.dorbae.test.Driver").newInstance(); // equivalent to Class.forName( "pe.dorbae.test.Driver", true, this.getClass().getClassLoader())
  
 }
}




Calling Class.forName( String, false, ClassLoader).newInstance()
1
2
3
4
5
6
public class Test {
 public static void main(String[] args) throws Exception {
  Class.forName( "pe.dorbae.test.Driver", false, Thread.currentThread().getContextClassLoader()).newInstance();
  
 }
}




When use JDBC driver, we usually call Class.forName( String driverClass). Class.forName( String) is not create JDBC Driver Object instance. If so, how to use driver object?

JDBC Driver generally make driver class that implements java.sql.Driver like this.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public final class <DriverClass> implements java.sql.Driver {

    static {
        try {
            DriverManager.registerDriver(new <DriverClass>());
        } catch (SQLException e) {
            throw new RuntimeException("Could not register driver", e);
        }
    }

    .
    .
    .
    
}

Therefore, if you call Class.forName( String driverClass), static block is called and it register new driver class instance.

However, it is different when JDBC Driver class is loaded in another. DriverManager.getConnection() finds driver object in Thread.current.getContextClassLoader().  DriverManager can't not find driver object, because it is actually loaded in another class loader.

In this case, you should like this.
1
2
java.sql.Driver driver = ( java.sql.Driver)Class.forName( DriverClassName, true, AnotherClassLoader).newInstance();
java.sql.Connection conn = driver.connect( <URL>, <Properties>);

No comments:

Post a Comment