Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing constructor from abstract base class with reflection

I'm playing around with Java's Reflection. I have an abstract class Base with a constructor.

abstract class Base {
    public Base( String foo ) {
        // do some magic
    }
}

I have some further classes extending Base. They don't contain much logic. I want to instantiate them with Base's constructor, without having to write some proxy contructors in those derived classes. And of course, I want to instantiate those derived classes with Reflection. Say:

Class cls = SomeDerivedClass.class;
Constructor constr;
constr = cls.getConstructor( new Class[] { String.class } ); // will return null
Class clsBase = Base.class;
constr = clsBase.getConstructor( new Class[] { String.class } ); // ok
Base obj = (Base) constr.newInstance( new Object[] { "foo" } ); // will throw InstantiationException because it belongs to an abstract class

Any ideas, how I can instantiate a derived class with Base's constructor? Or must I declare those dumb proxy constructors?

like image 954
craesh Avatar asked Jan 13 '11 16:01

craesh


People also ask

Can an abstract base class have a constructor?

Yes, an abstract class can have a constructor in Java. You can either explicitly provide a constructor to the abstract class or if you don't, the compiler will add a default constructor of no argument in the abstract class.

Can we call private constructor using reflection?

You can access a private constructor of a class via reflection and thus can instantiate it.

How can we use constructor in abstract class?

A constructor is used to initialize an object not to build the object. As we all know abstract classes also do have a constructor. So if we do not define any constructor inside the abstract class then JVM (Java Virtual Machine) will give a default constructor to the abstract class.

Can we define constructor in abstract class?

Yes, we can define a parameterized constructor in an abstract class.


3 Answers

A class does not inherit constructors from it parent. A class does not have it parents constructors (though it can call them) So you have to call the constructors the class has, not a constructor a super class has.

The default constructor only appears to do this because it calls the default constructor of the parent by default. If the parent doesn't have a default constructor, neither can its immediate children.

like image 126
Peter Lawrey Avatar answered Sep 23 '22 09:09

Peter Lawrey


I'm afraid your subclasses won't even compile until you have an explicit constructor in them calling one of the super() constructors.

like image 24
biziclop Avatar answered Sep 23 '22 09:09

biziclop


You cannot construct an abstract class without specifying all of the details that will make it "non-abstract".

That means in the example:

public abstract class Parent {
  String name;

  public Parent(String name) {
    this.name = name;
  }

  abstract public String getName();

}

no amount of constructor manipulating via reflection will return a Parent-only class. You can however, return an "anonymous" class by specifying the abstract details at construction time, like so:

Parent parent = new Parent() {
    public String getName() { return "Bob"; }
  };

Remember, sub-classing also calls the parent constructor, even if you don't put the code in explicitly. A sub-class written like:

public class Child extends Parent {
  public Child(String name) {
  }
}

will look for a no arg constructor in the Parent class. If it finds one, then it will be compiled into code equivalent to

public class Child extends Parent {
  public Child(String name) {
    super();
  }
}

If it doesn't find a no argument constructor in the Parent class, it will fail to compile until you explicitly specify the parent class construction with the super(name); constructor call.

Another thing to remember, all classes are subclasses of Object, so if you don't provide an extends SomeClass like so:

public class JustMe {
}

The compiler conceputally "corrects" you code at compile time to:

public class JustMe extends Object {

   public JustMe() {
     super();
   }
}

The Object class has a bunch of native (non-Java) code within it to register with the JVM ensuring correct garbage collection, memory management, type enforcement, etc. are followed over the life of the Object.

ie. You can't get around it, the JVM will stop you from constructing and abstract class unless all of it's methods can be resolved via anonymous classes or subclasses.

like image 28
Edwin Buck Avatar answered Sep 20 '22 09:09

Edwin Buck