Frank Haubenreisser Frank Haubenreisser - 3 months ago 5x
Java Question

Return an object of child class from abstract base class

I have classes that I want to (de-)serialize. I don't want the code to appear in every class, so I thought I'll make child classes like this

public class Swan extends Animal {}

and a base class like this:

public abstract class Animal {
protected String name;
// ...

public void saveAnimal(String filename) {
//ObjectOutputStream, save name...

public static /*returntype*/ loadAnimal(String filename) {

Basically I want this to work:

Swan s1 = new Swan("name");
Swan s2 = (Swan)loadAnimal("/pathToSaveFile") OR
Swan s2 = loadAnimal("/pathToSaveFile")

How do I do this if Animal is abstract? If the method looks like this:

public static <T extends Animal> T loadAnimal(String filename) {

I cannot return
new T(name) //parameter cannot be instantiated directly
. I read a bit about reflection but you cannot get the class of a generic type T. The workaround for this is to pass the class of the type into a constructor, but Animal should be abstract.


Due to type erasure you can't do exactly what you want, but here is some code that shows three options:

public class Foo {

    public static class Animal {
        public void save(String filename)
            // Write to file
        public static <T extends Animal> T load(String filename, Class<T> cls) throws Exception
            T result = cls.newInstance();
            // initialize result
            return result;

    public static class Swan extends Animal {
        public static Swan load(String filename) throws Exception
            return load(filename, Swan.class);

    public static void main(String[] args) throws Exception
        Swan s = new Swan();"somefile");
        Swan s2 = Swan.load("somefile", Swan.class);
        // OR equivalently
        Swan s3 = Animal.load("somefile", Swan.class);
        // OR also equivalent
        Swan s4 = Swan.load("somefile");

In order to instantiate T you have to have access to the Class object so you can do newInstance(). This requires a no-arg constructor or some more code to find and invoke the proper constructor, but that's basic reflection. You can hide the need for the Class if you provide a load method in Swan. Note that this is not an override, as inherited static methods don't participate in polymorphism. Swan.load merely hides the equivalent method from Animal.