karimvai
karimvai

Reputation: 319

Difference between calling a class constructor and using Class.forName().newInstance

I have been trying to understand the difference between using new to instantiate an object vs using Class.forName("A").newInstance();.

I have run the following code for a simple class A which shows using Class.forname("A").newInstance() is 70-100 times slower than using just new A().

I am curious to know why there is such a difference in time, but couldn't figure out. Please someone help me to understand the reason.

public class Main4test {

    public Main4test() {
    }

    static int turns = 9999999;

    public static void main(String[] args) {
        new Main4test().run();
    }

    public void run() {
        System.out.println("method1: " + method1() + "");
        System.out.println("method2:" + method2() + "");
    }

    public long method2() {
        long t = System.currentTimeMillis();
        for (int i = 0; i < turns; i++) {
            try {
                A a = (A) Class.forName("A").newInstance();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return System.currentTimeMillis() - t;
    }

    public long method1() {
        long t = System.currentTimeMillis();
        for (int i = 0; i < turns; i++) {
            try {
                A a = new A();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return System.currentTimeMillis() - t;
    }

}

public class A {
    int a;
    public A() {
    a=0;
    }
}

Upvotes: 20

Views: 6567

Answers (5)

Nir Alfasi
Nir Alfasi

Reputation: 53525

Using reflection Class.forName("A").newInstance(); is not only a costly operation (because the correct class-loader needs to be delegated to and load the class during runtime), but also makes your code more difficult to debug and you lose all the advantage of type safety (which takes place during compilation).

Conclusion:
Avoid reflection unless you must use it (for example if you're writing aspect-oriented plugin/library)

Upvotes: 5

user207421
user207421

Reputation: 310885

A a = new A();

Calls the new operator and the constructor of A directly, where A is mentioned in the source text and has therefore already been loaded and initialized.

A a = (A) Class.forName("A").newInstance();
  • look to see if A has already been loaded
  • load it if necessary
  • initialize it if necessary
  • locate the no-args constructor via reflection
  • call the new operator and the no-args constructor via reflection
  • typecast the result to A

Upvotes: 25

Vipul Paralikar
Vipul Paralikar

Reputation: 1568

The difference between new operator and newInstance method is listed below:

  • new operator can be used with any constructor of the class by passing any number of arguments as accepted by the constructor. newInstance method requires the presence of no-arg constructor in the class for which it has been invoked. If you want to use a constructor with newInstance, then you need to get an instance of Constructor class for any constructor and then invoke newInstance like:

    Class class = Class.forName("A");  
    Constructor const = class.getConstructor(A.class);  
    A a = null;  
    const.newInstance(a);
  • Using new operator doesn’t require explicit class loading as it is internally handled by the JVM. For newInstance() method an instance of that class’s Class object is required (Class.forName(“A”).newInstance(); or as shown in above point). The Class object referring to the underlying class is obtained by invoking the forName method.

  • The use of new operator is recommended when the name of class is known at compile time. Since newInstance uses reflection to create an object of class, it is recommended to be used when the class is not known at compile time but is determined at run time.

  • Since there is no extra processing related to method invocation like forName in new operator, it is faster than newInstance. The use of newInstance results in extra processing on part of JVM (type checks, security checks) and hence is not recommended to be used for performance degradation reasons.(at least when thousands of instances are being created using newInstance)

  • All Java developers are supposed to know the new operator as it is basic concept which is taught at beginner level, so there is nothing special to learn about it. Not all developers working on a application be aware of reflection and hence there is a learning curve for beginners working on the code with newInstance method.

  • You can see new operator being used in any normal Java program. newInstance is being used at multiple places inside Java especially in server side like loading and instantiating servlets, applets, JNDI stub/skeletons, JDBC database drivers.

  • With new operator, the class loading and object creation is done by the default class loader of JDK.But with newInstance method, one can explicitly specify the class loader to be used for loading class and object instantiation.

  • There are very less chances for runtime exception with new operator. Only rare case is when the class was present during compile time but was not available on classpath during runtime. The use of newInstance method with Class.forName(String …) can result in runtime exception even if the class name passed as argument to forName method is invalid.

  • The use of new operator results in generation of corresponding byte code in the .class file. When newInstance is used, there is no extra byte code generated for object creation inside the class as object creation is handled dynamically.

  • With new operator there is inherent type checking and compiler error is shown if the class doesn’t exist. Since the class name is passed as argument to Class.forName method as string, there is no compile type checking and usually results in run time exception as described in one of the earlier points.

Ref: http://www.javaexperience.com/difference-between-new-operator-and-class-forname-newinstance/

Upvotes: 4

Infinite Recursion
Infinite Recursion

Reputation: 6557

The primary difference between the conventional new and newInstance is that newInstance allows the flexibility to instantiate a class that you don't know until runtime, and makes your code more dynamic. When the class is not known until runtime, then it is a valid case where you should use reflection.

From the Javadoc, the invocation Class.forName(String) returns the Class object associated with the class or interface with the given string name i.e. it returns the Class A

So A a = (A) Class.forName(“A”).newInstance() breaks down to:

  • Class.forName(“A”)
    returns the Class A of type Class.

  • Class.forName(“A”).newInstance() Creates a new instance of the class represented by this Class object, so you get an instance of type A. The class is instantiated as if by a new expression with an empty argument list. The class is initialized if it has not already been initialized. This is here actually equivalent to a new A() and which returns a new instance of A.

    Important: Use of this method effectively bypasses the compile-time exception checking that would otherwise be performed by the compiler.

Reference:

Upvotes: 2

Peter
Peter

Reputation: 5798

the test you use to measure speed is not a valid test. Java performance is very complex and it involves hotspot vm, smart compilers and garbage collectors to start with.

In method 1 java wil be usually smart enough to only make 1 instance of A in memory and reuse it for each iteration

in method 2 you are forcing the VM to use reflection and classloaders to make the Object. that in itself is already slower

Upvotes: -2

Related Questions