【问题标题】:How to convert generic parameter to a class如何将泛型参数转换为类
【发布时间】:2013-03-14 00:54:53
【问题描述】:
public abstract class BaseDaoImpl<E extends AbstractEntity> implements BaseDao<E> {

    .....

    public BaseDaoImpl() throws DataAccessException {
        logger = LoggerFactory.getLogger(E);  <<-- error here.
    }

在上面的代码中,我在调用getLogger(E) 时遇到错误。

E 无法解析为变量

这是有道理的,但getLogger(E.class)(或其变体)也不起作用。

我不想在构造函数中传递文字类,因此无法选择将构造函数标头更改为:
public BaseDaoImpl(Class&lt;E&gt; clazz) ...

如何从E 获取类类型?

请注意以下问题的答案:How to get class of generic type when there is no parameter of it?
不帮忙。

【问题讨论】:

  • 你不能,因为类型擦除。
  • Java 泛型与 C++ 模板不同。使用 Java 泛型,类型在编译时被删除。谷歌“java类型擦除”了解详情。这似乎是一个糟糕的决定,但实际上是一个伟大的决定;因为它与旧的 java 完全向后兼容。

标签: java generics


【解决方案1】:

如果不更改构造函数,您将无法在运行时了解有关 E 的任何静态信息。这是因为在 Java 中,泛型参数根本没有任何运行时影响——编译器从字面上删除了它生成的代码中对 E 的所有引用。因此,如果您希望代码能够判断其类型参数被实例化的类,您必须自己添加某种参数(例如Class 对象)。就是没有办法解决。

【讨论】:

  • 我在尝试理解List.toArray() 时偶然发现了这一点,这令人失望。我知道类型擦除是作为一种成本/复杂性削减措施完成的,但它确实让事情半生不熟。至少,隐式 Class 参数可以添加到泛型函数中,这允许运行时通过管道输入泛型类型 E 的元数据。
【解决方案2】:

正如@CorayThan 指出的那样,可以通过反射来实现。一个简单的方法是从方法签名

interface BaseDao<E>
    E find(long id);

class FooDao implements BaseDao<Foo>
    Foo find(long id)

所以可以通过类型E找到

this.getClass().getDeclaredMethod("find", long.class).getReturnType();

然而,在构造函数中传递Class 是一个很好的选择。因为构造函数不打算由用户代码调用,所以这里的详细程度不是问题。

abstract class BaseDaoImpl<E>

    BaseDaoImpl(Class<E> clazz)

class FooDao extends BaseBaoImpl<Foo>

    FooDao()
        super(Foo.class);

// usages:

BaseDao<Foo> fooDao = new FooDao(); // clean & simple API

【讨论】:

  • “有可能” 一般情况下不会。如果您改为使用class FooDao&lt;E&gt; implements BaseDao&lt;E&gt; 怎么办?
【解决方案3】:

因为泛型是在 Java 语言中使用类型擦除实现的,所以您不能做任何需要运行时类型信息的事情。请参阅this page 了解更多信息。

【讨论】:

    【解决方案4】:

    已经是answered

    基本上,除非你使用反射,否则你不能。

    我不建议使用反射,但如果你愿意,你应该可以使用:

    GenericClass.class.getTypeParameters()
    

    【讨论】:

    • 这通常是不正确的。例如,如果我有class Foo&lt;E&gt; extends BaseDaoImpl&lt;E&gt;,那么你仍然无法得到它。
    • 如果你有class Foo&lt;Admin&gt; extends BaseFoo&lt;? extends User&gt;,它应该可以工作。如果你想获得 E 的类,显然你会遇到问题,因为 E 不是类!
    • 获取Type 与获取Class 不同
    猜你喜欢
    • 1970-01-01
    • 2010-10-25
    • 1970-01-01
    • 2013-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多