Java中的泛型和反射

Java中的泛型和反射,java,generics,reflection,Java,Generics,Reflection,这可能是一个非常基本的问题,但我对Java中的泛型非常陌生,我很难改变我在C#中的思维过程,所以请耐心听我说 我正在尝试用Java构建一个通用存储库。我创建了一个IRepository界面,如下所示: public interface IRepository<T extends IEntity> public class Repository<T extends IEntity> implements IRepository<T> IRepository&

这可能是一个非常基本的问题,但我对Java中的泛型非常陌生,我很难改变我在C#中的思维过程,所以请耐心听我说

我正在尝试用Java构建一个通用存储库。我创建了一个IRepository界面,如下所示:

public interface IRepository<T extends IEntity>
public class Repository<T extends IEntity> implements IRepository<T>
IRepository<MyClass> repo = new Repository<MyClass>();
公共接口IRepository
以及一个如下所示的存储库类:

public interface IRepository<T extends IEntity>
public class Repository<T extends IEntity> implements IRepository<T>
IRepository<MyClass> repo = new Repository<MyClass>();
公共类存储库实现了IRepository
现在,在我的Repository类的构造函数中,我希望能够“预言”T的确切类型。例如,如果我实例化了一个类似于以下内容的存储库:

public interface IRepository<T extends IEntity>
public class Repository<T extends IEntity> implements IRepository<T>
IRepository<MyClass> repo = new Repository<MyClass>();
IRepository repo=new Repository();

我想知道T实际上是我的班级。这在C#中是微不足道的,但显然泛型在Java中是一个完全不同的野兽,我似乎找不到任何东西可以帮助我做到这一点。

Java使用,因此特定信息在运行时丢失-您只知道这种类型是泛型,您在编译时提供的具体参数不是什么。

我也做了类似的事情(也是为了实现存储库/注册表模式),通过一些工作,您可以实际找到类型。但是请注意,我并没有使用接口,而是使用一个基类来完成这项工作,还请注意,要找到一个有效的解决方案,需要经过一些尝试和错误。这段代码是在Sun JVM上运行的,所以我可能无意中发现了一个特定于JVM的领域

此外,正如另一条评论所提到的,仅仅因为你可以做到这一点,并不意味着你一定应该:)

import java.lang.reflect.ParameterizedType;
...
公共静态类类型(对象目标){
Class base=target.getClass();
while(base!=null){
对象gsuper=base.getGenericSuperclass();
if(gsuper!=null&&gsuper instanceof ParameterizedType){
对象o=((ParameteredType)gsuper.getActualTypeArguments()[0];
if(类的o实例){
返回(类)o;
}
}
base=base.getSuperclass();
}
返回null;
}
我从我的BaseRepository类中使用了以下内容:

Class<?> type = type(SomeRepository);
Class type=type(SomeRepository);
其中:

public class SomeRepository extends Repository<MyEntity> {
... 
}
public类SomeRepository扩展存储库{
... 
}

您始终可以在构造函数中添加T的实际类型,如下所示:

public class Repository<T> implements IRepository<T>
  public Repository(Class<T> type) {
  }
}
公共类存储库实现了IRepository
公共存储库(类类型){
}
}
然后像这样实例化

IRepository<MyClass> repo = new Repository<MyClass>(MyClass.class);
IRepository repo=新存储库(MyClass.class);

特定信息丢失;通用信息是…通用的。:-)我认为这是正确的答案。这清楚地解释了为什么我最初想要用Java实现泛型是不可能实现的。只需扩展一点:知道运行时的实际类型违反了约定。合同规定,
IRepository
将包含
Entity
对象。如果您需要在实现中了解比
IEntity
更多的信息,则需要重构
IEntity
;否则,你将紧密结合<代码> IRepository <代码>到实现的类。如果你认真对待java,你应该考虑把i-记号放在后面。有人说它有很好的用途,但我认为当你使用java中的其他接口(如Map、InputStream等)时,它看起来不一致。从客户机代码(不使用反射)很难判断类型是接口还是抽象类(除非它有公共的非最终字段或其他东西),但这只有在您实际使用子类时才有帮助。。。不只是像OP那样实例化。这是一个很好的解决方法,但我认为它仍然会在链的更高层咬我一口。我想不出使用这种方法创建存储库工厂的方法。