Java中的泛型和反射

时间:2010-02-21 10:55:31

标签: java generics reflection

这可能是一个非常基本的问题,但我对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中完全不同的野兽,我似乎无法找到任何可以帮助我做到这一点的东西。

3 个答案:

答案 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> {
... 
}