具有通用java

问题描述

我正在尝试通过以下代码在Java 15中使用通用类

@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);
    }
}

由于使用此解决方案需要额外的代码,有没有更好的方法呢?

解决方法

单例类,其唯一的构造函数带有参数进行了参数化?

您的代码没有意义。在其他情况下,您遇到的问题很重要,但与此无关。没有直接解决此问题的方法(问题是:泛型被删除),但是有不同的代码样式可以避免这种情况。

问题在于,因为该问题甚至都不适用于这种情况,所以很难解释人们将如何重写此代码,从而使该问题作为一般原理消失。

在这里,您只是...删除类型参数,摆脱该接口(通常,如果您有IFoo徘徊,那是不对的),就这么简单。

如果您想对此概念进行概括,以便可以做很多(假设您有一个此类可以检索Foos,而另一个可以检索Bars),则可以获取{{1} },特别是在<X>中,尽管有点棘手(您可以从自己的public class FooFetcher implements GenericFetcher<X>中使用getGenericSuper,然后从那里获取。在这种情况下,有很多警告,所以我赢了对此不做进一步扩展,只知道您可以做到这一点。

如果在另一种情况下确实需要以可在运行时查询的方式传达泛型,则样式的问题是java.lang.Classa class object重叠但不相同。 a generics param有一个类对象(int),但是int.class不是有效的Java代码。 List<int>是有效的泛型(List<String>是有效的Java),但是List<List<String>> x;不是事物,永远不会,只有List<String>.class是。 List.class?也是如此,这是有效的泛型,但显然根本无法用? extends Map<?,List<? extends Number>> & Serializable类型表示。因此,如果您确实希望将泛型作为运行时可查询的概念,请在网络上搜索“超级类型令牌”,但请注意,它们所需的代码比此处的更多,而不是更少。它们实际上实际上能够准确地代表泛型。

作为一般经验法则,如果您依靠java.lang.Class的泛型将代码粘合在一起,那么您做错了什么,并且您可能想要工厂。