从抽象基类返回子类的对象

Fra*_*ser 6 java abstract-class

我有一些想要序列化(反序列化)的类。我不希望代码出现在每个类中,所以我想我会创建这样的子类

public class Swan extends Animal {}
Run Code Online (Sandbox Code Playgroud)

和这样的基类:

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


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

   public static /*returntype*/ loadAnimal(String filename) {
       //ObjectInputStream...
   }
}
Run Code Online (Sandbox Code Playgroud)

基本上我希望这个工作:

Swan s1 = new Swan("name");
s1.saveAnimal("/pathToSaveFile");
Swan s2 = (Swan)loadAnimal("/pathToSaveFile") OR 
Swan s2 = loadAnimal("/pathToSaveFile")
Run Code Online (Sandbox Code Playgroud)

如果 Animal 是抽象的,我该怎么做?如果该方法如下所示:

public static <T extends Animal> T loadAnimal(String filename) {
    //loadFromFile
    }
Run Code Online (Sandbox Code Playgroud)

我无法返回new T(name) //parameter cannot be instantiated directly。我读了一些有关反射的内容,但无法获取泛型类型 T 的类。解决方法是将类型的类传递给构造函数,但 Animal 应该是抽象的。

Jim*_*son 4

由于类型擦除,您无法完全执行您想要的操作,但这里有一些代码显示了三个选项:

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();
        s.save("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");
    }
}
Run Code Online (Sandbox Code Playgroud)

为了实例化,T您必须有权访问该Class对象,以便您可以执行操作newInstance()。这需要一个无参数构造函数或更多代码来查找和调用正确的构造函数,但这是基本的反射。如果您在 中Class提供方法,则可以隐藏对 的需求。请注意,这不是重写,因为继承的静态方法不参与多态性。 只是隐藏了等效方法。loadSwanSwan.loadAnimal