Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to anonymously instantiate an abstract class stored in a Class object in Java?

If you have an abstract class you can instantiate it by deriving an concrete anonymous class. This is an example:

abstract class A {
     abstract void hello ();
}

A say = new A () { void hello () { System.out.println ("hello"); } }

say.hello(); // -> hello

How to do the same if the class is stored in a Class object? Here is an example:

// -*- compile-command: "javac anon.java && java anon"; -*-

class anon
{
    anon () throws Exception {}

    abstract class AbstractClass
    {
        AbstractClass () throws Exception {}
        abstract void id ();
    }

    AbstractClass x = new AbstractClass ()
        {
            void id () { System.out.println ("X"); }
        };

    Class<AbstractClass> abstractclass 
        = (Class<AbstractClass>)Class.forName ("anon$AbstractClass");

    AbstractClass y = abstractclass.getConstructor().newInstance();

    public static void main (String argv[]) throws Exception
    {
        anon main = new anon();
        main.x.id(); // should print "X"
        main.y.id(); // should print "Y"
    }
}

The first instantiation (x) works fine but the second (y) fails because it tries to instantiate the abstract class directly without deriving a concrete class. How can I do this in Java having only a Class object?

like image 439
ceving Avatar asked Nov 29 '12 10:11

ceving


People also ask

How do you instantiate an abstract class in Java?

Abstract classes cannot be instantiated, but they can be subclassed. When an abstract class is subclassed, the subclass usually provides implementations for all of the abstract methods in its parent class. However, if it does not, then the subclass must also be declared abstract .

Can an anonymous class be instantiated?

Anonymous classes enable you to make your code more concise. They enable you to declare and instantiate a class at the same time. They are like local classes except that they do not have a name.

Can you instantiate objects of an abstract class no yes?

We cannot instantiate an abstract class in Java because it is abstract, it is not complete, hence it cannot be used.


2 Answers

You may have a misunderstanding on how exactly anonymous classes work. An anonymous class is in fact a regular class just like any other and has its own class file. Java-the-language only provides some syntactic sugar over this and allows a less verbose syntax for something that you can exactly mimic by declaring a regular named top-level class in its own file. This is why you will find the Reflection API useless for what you want to achieve. Basically, you want to dynamically create a class that doesn't have its class file. For this you need a suitable library, such as javassist.

like image 63
Marko Topolnik Avatar answered Oct 06 '22 00:10

Marko Topolnik


If A would be an interface instead of an abstract class, you can do this with a dynamic proxy, but that doesn't work with an abstract class. Example of how this works with an interface:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface A {
    void hello();
}

public class Example {
    public static void main(String[] args) throws Exception {
        @SuppressWarnings("unchecked")
        Class<A> cls = (Class<A>) Class.forName("A");

        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args)
                    throws Throwable {
                System.out.println(method.getName());
                return null;
            }
        };

        A instance = (A) Proxy.newProxyInstance(cls.getClassLoader(),
            new Class<?>[] { cls }, handler);

        instance.hello();
    }
}
like image 24
Jesper Avatar answered Oct 06 '22 01:10

Jesper