这可能是一个非常基本的问题,但我对Java中的泛型来说真的很陌生,而且我很难用C#中的事情来改变我的思维过程,所以请耐心等待。
我正在尝试用Java构建通用存储库。我创建了一个如下所示的IRepository接口:
public interface IRepository<T extends IEntity>
一个看起来像这样的Repository类:
public class Repository<T extends IEntity> implements IRepository<T>
现在,在我的Repository类的构造函数中,我希望能够“确定”T的确切类型。例如,如果我实例化了这样的存储库:
IRepository<MyClass> repo = new Repository<MyClass>();
我想知道T实际上是MyClass。这在C#中是微不足道的,但显然泛型是Java中完全不同的野兽,我似乎无法找到任何可以帮助我做到这一点的东西。
答案 0 :(得分:5)
Java使用type erasure,因此特定信息在运行时丢失 - 您只知道此类型是通用的,而不是您在编译时提供的特定参数。
答案 1 :(得分:2)
您始终可以在构造函数中添加实际的T类型,如下所示:
public class Repository<T> implements IRepository<T>
public Repository(Class<T> type) {
}
}
并实例化
IRepository<MyClass> repo = new Repository<MyClass>(MyClass.class);
答案 2 :(得分:0)
我做过类似的事情(也是为了实现Repository / Registry模式),通过一些工作,你可以真正找到类型。但请注意,我没有使用接口,但使用基类,并且还注意到需要一些试验和错误才能找到有效的解决方案。此代码在Sun JVM上运行,因此可能是我偶然发现了一个特定于JVM的区域。
另外 - 正如另一条评论所提到的,仅仅因为你可以做到这一点,并不意味着你一定应该:)
import java.lang.reflect.ParameterizedType;
...
public static Class<?> type(Object target) {
Class base = target.getClass();
while (base != null) {
Object gsuper = base.getGenericSuperclass();
if (gsuper != null && gsuper instanceof ParameterizedType) {
Object o = ((ParameterizedType) gsuper).getActualTypeArguments()[0];
if (o instanceof Class) {
return (Class<?>) o;
}
}
base = base.getSuperclass();
}
return null;
}
我在我的BaseRepository类中使用了它,如:
Class<?> type = type(SomeRepository);
其中:
public class SomeRepository extends Repository<MyEntity> {
...
}