使用泛型 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 object
和 a 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 的泛型将您的代码粘合在一起,那么您就做错了,您可能需要工厂。
我正在尝试使用 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 object
和 a 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 的泛型将您的代码粘合在一起,那么您就做错了,您可能需要工厂。