2010-09-01 26 views
6

(这有点后随我previous question如何获取Foo <?>对象的<?>值?

我有一个Foo<?>对象,fooFoo<T>是一个界面。

如何获取隐藏在<?>后面的类型值?

注意,这是不平凡的,因为foo可以是例如Bar<String>类,其中Bar<T> implements Foo<T>的目的,或一些anonyomus类实现接口FloatFoo,其中FloatFoo extends Foo<Float>。我需要一个适用于所有情况的解决方案。

感谢提前:)

+0

Foo是你自己的界面吗?你能够实现其他方法吗? – Arne 2010-09-01 08:10:33

+0

是的,我想过 - 'getType()'方法可以解决这个问题。可能我会得到这样的解决方案。 – mik01aj 2010-09-01 08:45:34

回答

2

final-final(也许是最好的)解决方案:我重构了我的代码,所以它不需要这个。我将所有需要类型参数的代码移动到Foo中,以便在课程中提供适当的实现。结果代码少得多。

9

这是不可能的使用反射,因为Java的泛型有Type Erasure问题。在运行时,为通用类Foo定义的类型已被删除,因此对该类使用反射将不会产生其泛型类型。此类型信息仅用于编译类型安全。

C#没有这个问题,并且可以访问类的模板化类型。

This是差异的概述。

8

好吧,简而言之,你不能。

但是,使用FloatFoo时,您可以执行的操作是获取<?>的值。

事实上,从我记忆中,泛型不保存在课堂信息中。但是,当您创建泛型类型的子类型(无论是类还是接口)时,必须记忆泛型信息,因为它可能会定义某些子类型的方法签名。

举个例子,如果你的Foo interfaceis声明它:

​​

有一个

public interface FloatFoo extends Foo<Float> 

意味着这个接口已申报

public Float doIt(); 

方法。

为此,编译器必须具有类型信息。这个信息将反映在反射API中,因为FloatFoo的超类将有一些与它相关的类型参数。或者至少它是我从我遇到过这种情况的少数案件(或详述它们,因为它有时可能是强制性的)中记得的。

但是,您将在Angelika's generics FAQ获得更完整的信息。

+0

问题是,'getMethod(“doIt”)。getReturnType()'返回'Object',如果你要运行该方法来查看它返回的内容,有时候你会得到一个子类对象,有时候会得到'null'。 – mik01aj 2010-09-01 08:19:40

+3

相关,也许有帮助:http://www.artima.com/weblogs/viewpost.jsp?thread=208860 – Arne 2010-09-01 08:22:31

+0

@ m01 Riduidel提到的接口技巧并不总是工作。它被提及作为存在的一些数据的一个例子,但潜在的问题仍然存在。 Arne提到的链接引用了由Java编译器开发人员之一Neal Gaffer创建的解决方法。 – linuxuser27 2010-09-01 08:28:15

1

我结束了创建与界面中的getType()方法:

Class<T> getType(); 

也许这不是最完美的解决方案,但绝对是最简单的一种。

+1

如果您的(比如说,列表)仍然不起作用。你可以返回的最好是List.class。如果情况变得复杂,请查看“超级类型令牌”模式:http://gafter.blogspot.com/2006/12/super-type-tokens.html – 2010-09-03 21:19:15

相关问题