使用泛型 java 键入参数 Class

Type Parameter Class with generic java

我正在尝试使用 java 15 中的通用 class 和以下代码

@Singleton
public class GenericRepository<T> implements IGenericRepository<T>{
    private final MongoClient mongoClient;
    
    public GenericRepository(MongoClient mongoClient) {
        this.mongoClient = mongoClient;
    }

    public MongoCollection<T> getCollection(String collectionName) {
        return mongoClient
                .getDatabase("main")
                .getCollection(collectionName, T.class);
    }
}

我无法使用T.class,我该如何解决

我找到的解决方案

@Singleton
public class GenericRepository<T> implements IGenericRepository<T>{
    private final MongoClient mongoClient;
    private final Class<T> typeParameterClass;

    public GenericRepository(MongoClient mongoClient, Class<T> typeParameterClass) {
        this.mongoClient = mongoClient;
        this.typeParameterClass = typeParameterClass;
    }

    public MongoCollection<T> getCollection(String collectionName) {
        return mongoClient
                .getDatabase("main")
                .getCollection(collectionName, this.typeParameterClass);
    }
}

由于使用这个解决方案需要额外的代码,有没有更好的方法来做到这一点?

一个单例class,其唯一的构造函数带参数,被参数化了?

你的代码毫无意义。您 运行 遇到的问题在其他情况下很重要,但在这个问题上却不是。这个问题没有直接的解决方案(问题是:泛型被删除),但是有不同的代码风格可以避免它。

问题是,因为这个问题甚至不适用于这种情况,所以很难解释如何重写这段代码,所以这个问题作为一般原则就消失了。

在这里,您只需...删除类型参数,摆脱该接口(通常,如果您有 IFoo 闲逛,有些不对劲),就这么简单。

如果你想概括这个概念,这样你就可以做很多这样的事情(假设你有一个 classes 来检索 Foos,另一个来检索 Bars),你可以在特定的 public class FooFetcher implements GenericFetcher<X> 中获取 <X>,尽管这有点棘手(你可以使用你自己的 java.lang.Class 中的 getGenericSuper 然后从那里获取它。有很多警告在这种情况下,所以我不会对此进行任何进一步的扩展,只知道你可以这样做。

如果在不同的情况下,您确实需要以 runtime-queryable 的方式传达泛型,那么您的风格的问题是 a class objecta generics param 重叠但不重叠相同。 int 有一个 class 对象 (int.class),但是 List<int> 不是有效的 java 代码。 List<String> 是有效的泛型(List<List<String>> x; 是有效的 java),但是 List<String>.class 不是而且永远不会是,只有 List.class 可以。 ?? extends Map<?, List<? extends Number>> & Serializable 也是如此,这是有效的泛型,但显然根本不是可以用 java.lang.Class 类型表示的东西。因此,如果您确实希望将泛型作为运行时可查询的概念,请在网上搜索 'super type tokens' - 但请注意,它们需要的代码比您在此处拥有的代码更多,而不是更少。它们实际上能够准确地表示泛型可以表示的内容。

根据一般经验法则,如果您依赖 java.lang.Class 的泛型将您的代码粘合在一起,那么您就做错了,您可能需要工厂。