Create an instance within Abstract Class using Ref

2019-02-23 00:16发布

问题:

Is it possible to create an instance of a derived class in abstract ancestor class using reflection Lets say:

abstract class Base {

public Base createInstance(){
  //using reflection
    Class<?> c = this.getClass();
    Constructor<?> ctor = c.getConstructor();
    return ((Base) ctor.newInstance());
}

}//end Base

class Derived extends Base {

 main(){

new Derived().createInstance()

 }

}

回答1:

You can do this

public class Derived extends Base {
    public static void main(String ... args) {
        System.out.println(new Derived().createInstance());
    }
}

abstract class Base {
    public Base createInstance() {
        //using reflection
        try {
            return getClass().asSubclass(Base.class).newInstance();
        } catch (Exception e) {
            throw new AssertionError(e);
        }
    }
}

prints

Derived@55fe910c

A more common pattern is to use Cloneable

public class Derived extends Base {
    public static void main(String ... args) throws CloneNotSupportedException {
        System.out.println(new Derived().clone());
    }
}

abstract class Base implements Cloneable {
    @Override
    public Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}

prints

Derived@8071a97

However, the need to use either should be avoided. Usually there is another way to do what you need so that base doesn't not implicitly depend on derived.



回答2:

Proving it works is easy:

abstract class Base {
  public Base createInstance() throws Exception {
    return getClass().newInstance();
  }
}

public class Derived extends Base {
  public static void main(String[] args) throws Exception {
    System.out.println(new Derived().createInstance().getClass());
  }
}

prints

class test.Derived

You should ask yourself twice why you need it and whether it is really a good approach for your problem. If you need cloning, consider the clone mechanism, which does basically the same thing.



回答3:

You can use Class.forName() and Class.newInstance() to create any class. But there's no way to easily identify subclasses of a class. See this JavaWorld tip for a technique to do this.

I think , however, the real issue is what is it you're ultimately trying to achieve, and can it be done more easily using conventional techniques.