Java: Difference between Class.forName and ClassLoader.loadClass

前端 未结 5 1778
故里飘歌
故里飘歌 2020-12-22 23:51

What is the difference between Class.forName and ClassLoader.loadClass in the following codes:

Class theClass = Class.forName("         


        
相关标签:
5条回答
  • 2020-12-23 00:24

    When use you use Class.forName("SomeImpl"), you're obtaining the class via the current classloader (i.e. the loader of the class that you're making the method call in). It will also initialize the class. It's effectively the same as calling Class.forName("SomeImpl", true, currentLoader) where currentLoader would be the caller's classloader. See the details here.

    The second method requires a classloader to be chosen first. Don't write it like ClassLoader.loadClass("SomeImpl") since it is not a static method. You'd require something like

    final ClassLoader cl = this.getClass().getClassLoader();
    Class theClass = cl.loadClass("SomeImpl");
    

    Mind that subclasses of ClassLoader should override the findClass method rather than loadClass. This is the same as calling the (protected) method loadClass("SomeImpl", false), where the second argument indicates whether linking should be done or not.

    There are more subtle differences... The loadClass method expects a binary class name as specified by the Java Language Specification, while forName could also be used with Strings representing primitive types or array classes.

    Overal, it's best to use Class.forName, if necessary specifying a specific classloader and whether it must be intialized or not, then let the implementation figure out the rest. Using classloaders directly is good for finding resources in a jar or on the classpath.

    0 讨论(0)
  • 2020-12-23 00:29

    Class.forName() will always use the ClassLoader of the caller, whereas ClassLoader.loadClass() can specify a different ClassLoader. I believe that Class.forName initializes the loaded class as well, whereas the ClassLoader.loadClass() approach doesn't do that right away (it's not initialized until it's used for the first time).

    Just found this article when looking to confirm my summary of the initialization behavior. It looks like this has most of the information you're looking for:

    http://www.javaworld.com/javaworld/javaqa/2003-03/01-qa-0314-forname.html

    This usage is pretty cool, though I've never used it before:

    Class.forName(String, boolean, ClassLoader)
    

    It allows you to specify a ClassLoader and the boolean parameter defines whether the class should be initialized when it's loaded or not.

    0 讨论(0)
  • 2020-12-23 00:32

    This line won't compile:

    Class theClass = ClassLoader.loadClass("SomeImpl");
    

    because loadClass is not a static method of ClassLoader.

    To fix this problem, create a ClassLoader object as follows in one of 3 possible ways:

    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    ClassLoader classLoader = Main.class.getClassLoader();      // Assuming in class Main
    ClassLoader classLoader = getClass().getClassLoader();      // works in any class
    

    then call:

    Class theClass = classLoader.loadClass("SomeImpl");
    

    -dbednar

    0 讨论(0)
  • 2020-12-23 00:34

    The loadClass() method can't be called as a static one. Create sub class for ClassLoader and have some additional other methods to do operations. Can create your own class loader by extendingClassLoader class. In functional both ways are same.

    0 讨论(0)
  • 2020-12-23 00:35

    Shaun's answer is more or less correct except few omissions/small errors:

    • Class.forName associates the class w/ the ClassLoader (regardless if any other parent loads it for real), hence ClassLoader.findLoadedClass is successful next time. That's a very, very important point, most ClassLoader would try Class c = findLoadedClass(name); if (c!=null) return c; as first statements bypassing the whole find/look up part. Calling ClassLoader.load directly will not add the class to the loaded ones.

    The case has implications when loaded via graph alike structure of ClassLoader, i.e. not using parent only to lookup first.

    • Initialization of the class is performed in loadClass of the ClassLoader w/ code like that: if (resolve) resolveClass(c); and the ClassLoader can actually skip resolve it it feels like, unrecommended but possible.

    What are the do's and dont's to using these two methods?

    Unless you have very strong idea why you want ClassLoader.loadClass(String), do not use it directly. In all other case, always rely on Class.forName(name, true, classLoader).

    Overall Class loading is next to an art and it cannot be covered in a simple answer (not joking about art part)

    0 讨论(0)
提交回复
热议问题