David
David

Reputation: 10738

java class to create instance of itself

I'm trying to create an instance of the holding class using reflection but i keep getting the following exception

java.lang.ClassNotFoundException: class com.myproject.fresh.stubClasses.TestModel at java.net.URLClassLoader$1.run(URLClassLoader.java:202) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:190) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301) at java.lang.ClassLoader.loadClass(ClassLoader.java:247) at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:171)

public class TestModel extends Model {

    @Override
    public Schema getSchema() {
        return schema;
    }

    public TestModel newModel(){

        TestModel model = null;

        try{

            Class<?> clazz = Class.forName(getClass().toString());
            Constructor<?> ctor = clazz.getConstructor();
            model = (TestModel) ctor.newInstance();

        } catch (Exception e){
            e.printStackTrace();
        }

        return model;
    }
}

What am i doing wrong?

Upvotes: 1

Views: 1705

Answers (3)

ccleve
ccleve

Reputation: 15779

What's wrong with using just getClass().newInstance()?

Upvotes: 0

ruakh
ruakh

Reputation: 183251

The problem is that getClass().toString() returns (for example) class com.myproject.fresh.stubClasses.TestModel, with a stray class at the beginning. If you use getName() instead, it should work:

Class<?> clazz = Class.forName(getClass().getName());

though if this is "real" code (rather than just figuring-stuff-out code), it's easier to just write this:

Class<?> clazz = getClass();

That also lets you make better use of generics:

Class<? extends TestModel> clazz = getClass();
Constructor<? extends TestModel> ctor = clazz.getConstructor();
model = ctor.newInstance();

or:

return getClass().getConstructor().newInstance();

Upvotes: 3

ApproachingDarknessFish
ApproachingDarknessFish

Reputation: 14313

This line here:

Class<?> clazz = Class.forName(getClass().toString());

is wrong.

Do not use the toString() method to get the class's name. Use getName() instead.

The following example describes their differences:

public class Test
{
    public static void main(String[] args)
    {
        System.out.println(Test.class.toString()); //prints "class <package>.Test"
        System.out.println(Test.class.getName()); //prints "<package>.Test"
    }
}

The extraneous "class" text before the class name is throwing off the 'forName' method.

In the end, this is what the line should look like:

Class<?> clazz = Class.forName(getClass().getName());

Upvotes: 3

Related Questions