Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which java.lang.Class method generates the right input for Class.forName()?

I would like to write some code like this:

Object o = ...;
String oTypeName = o.getClass().getName();

//on the other side of the wire:

Class<?> oClass = Class.forName(oTypeName);
Object oAgain = oClass.newInstance();

However, it's not clear from the javadoc which method I should use to initialize oTypeName, i.e. which method will produce the expected input to Class.forName():

  • getCanonicalName(): "Returns the canonical name of the underlying class as defined by the Java Language Specification. Returns null if the underlying class does not have a canonical name (i.e., if it is a local or anonymous class or an array whose component type does not have a canonical name)."
  • getName(): "Returns the name of the entity (class, interface, array class, primitive type, or void) represented by this Class object, as a String. If this class object represents a reference type that is not an array type then the binary name of the class is returned, as specified by The Java™ Language Specification."
  • getTypeName(): "Return an informative string for the name of this type."

It's fairly obvious that I don't want either of these:

  • getSimpleName(): "Returns the simple name of the underlying class as given in the source code."
  • toString(): "The string representation is the string "class" or "interface", followed by a space, and then by the fully qualified name of the class in the format returned by getName"

I don't expect this to work for primitive types. It's okay if it won't work for arrays. The main thing I'm concerned about is nested classes and Foo.Bar vs. Foo$Bar.

like image 358
Matt McHenry Avatar asked Jul 29 '16 20:07

Matt McHenry


People also ask

What is class forName () method in Java?

forName(String name, boolean initialize, ClassLoader loader) method returns the Class object associated with the class or interface with the given string name, using the given class loader. The specified class loader is used to load the class or interface.

Which type of exception will be thrown by forName () method in Java?

forName() method may throw an exception at the time of returning a Class object. LinkageError: This exception may throw when we get linking error. ExceptionInInitializeError: In this exception when the initialization is done by this method fails.

How do I load a class using forName?

Load class with forName() method in Java The class object associated with the class with the given string name can be returned with the method java. lang. Class. forName(String name, boolean initialize, ClassLoader loader), using the class loader that is used to load the class.

What is the actual purpose of class forName () method Mcq?

The forName() method of Java Class class returns the Class object associated with the class or interface with the given name in the parameter as String.


1 Answers

The definite answer is getName(). Although a bit hidden, this is specified in the Javadoc of the overload of forName(className, initialize, loader):

Given the fully qualified name for a class or interface (in the same format returned by getName) this method attempts to locate, load, and link the class or interface.

And it is also specified that calling forName(className) is equivalent to calling this overload, with default values:

Invoking this method is equivalent to:

Class.forName(className, true, currentLoader) 

where currentLoader denotes the defining class loader of the current class.


Here's a sample code showing that it works for nested classes, local classes, anonymous class, primitive or object arrays. It won't work for primitives because Class.forName doesn't handle primitive classes.

public class Main {
    public static void main(String... args) throws ClassNotFoundException {
        class LocalClass {}

        System.out.println(Class.forName(name(StaticNestedClass.class))); //static nested class
        System.out.println(Class.forName(name(InnerClass.class))); // inner class
        System.out.println(Class.forName(name(Integer[].class))); // object array
        System.out.println(Class.forName(name(int[].class))); // primitive array
        System.out.println(Class.forName(name(List.class))); // interface
        System.out.println(Class.forName(name(LocalClass.class))); // local class
        System.out.println(Class.forName(name(new Object(){}.getClass()))); // anonymous class
    }

    private static String name(Class<?> clazz) {
        return clazz.getName();
    }

    public static class StaticNestedClass {}
    public class InnerClass {}
}
like image 83
Tunaki Avatar answered Oct 23 '22 16:10

Tunaki