首页 > 解决方案 > 如何在 Java 中继承泛型静态方法?

问题描述

10 多年前,我问过这个关于 C# 的问题,并在那里得到了很好的答案。现在我正在尝试在 Java 中做同样的事情。

假设我有一个抽象类Animal。我想要该类中的静态方法create(),它将返回子类的类型的值。我使用以下结构在 C# 中管理它:

public class Animal<T> where T : Animal<T>, new()
{
    public static T Create()
    {
        var t = new T();
        // do generic stuff on the new T instance
        return t;
    }
}

public class Dog : Animal<Dog>
{

}

//usage:
var dog = Dog.Create();

这在 C# 中很有魅力。但现在我正试图在 Java 中复制这种结构,并且碰壁了。一大堵墙是您似乎不能拥有静态通用成员。因此,这似乎有点引人注目。但我是一个乐观的人,也许那里的一些 Java 专家已经提出了一个完全开箱即用的模式来或多或少地实现我在这里尝试做的事情?

标签: javagenerics

解决方案


问题是在 Java 中你不能像这样从类型变量中构造一个实例。

作为一种快速的替代方法,您可以使用您的代码通过具体的构造函数调用来辅助的工厂

@FunctionalInterface
interface AnimalFactory<T extends Animal> {
    T create();

    static <U extends Animal> AnimalFactory<U> ofClass(Class<U> type) {
        return () -> {
            try {
                return type.newInstance();
            } catch (Exception e) {
                // handle
                throw new RuntimeException(e);
            }
        };
    }

    static <U extends Animal> AnimalFactory<U> ofSupplier(Supplier<U> creator) {
        return creator::get;
    }
}

然后你可以在你的Animal静态方法中调用它(你确实可以将它重用于其他类型):

class Animal {
    static <T extends Animal> T create(Class<T> type) {
        T instance = AnimalFactory.ofClass(type)
                .create();
        // do generic stuff on the new T instance
        return instance;
    }

    static <T extends Animal> T create(Supplier<T> creator) {
        T instance = AnimalFactory.ofSupplier(creator)
                .create();
        // do generic stuff on the new T instance
        return instance;
    }
}

最后,您的调用代码如下所示。我使用了 lambda 和基于反射的方法。你选。

Dog d = Animal.create(Dog.class);
Dog e = Animal.create(Dog::new);

当然,您可以完全跳过静态方法AnimalAnimalFactory直接使用(接口现在可以具有可用于运行// do generic stuff on the new T instance逻辑的静态方法)


推荐阅读