检查泛型的实例?

5

你好,我有一个方法应该根据类型返回不同的结果。

我可以像这样检查泛型类型:

public <T> T search(final String query){
 T returnValue = null;
 if (returnValue instanceof String){ }
 if (returnValue instanceof Integer){ }
 if (returnValue instanceof MyObject){ }

但是我为什么不能这样做呢?(注:这句话没有上下文,无法确定更加精准的翻译)
public <T> T search(final String query){
 T returnValue = null;
 if (T instanceof String){ }
 if (T instanceof Integer){ }
 if (T instanceof MyObject){ }

调用代码。
String id = myObjcet.<String> search("select ...");
3个回答

4

Java通过"擦除"来实现泛型。这意味着在运行时几乎没有关于泛型的任何信息。相反,编译器会检查泛型,但在幕后将所有内容转换为Object(或最接近的泛型边界)。

如果您使用javap反编译该方法,您会看到它读取:

public Object search(...

移除所有对T的引用。

这是Java泛型的一个严重限制,这在JRE类中也经常反映出来,例如:

SomeClass<String> x = new SomeClass<String>(String.class);

第三次重复使用String(String.class)是因为构造函数需要知道它正在操作的类。

尽管这种范式很糟糕,但可以解决你的问题。

关于泛型的信息实际上包含在.class文件中,作为元数据,可以使用反射进行检查,并在某种程度上进行解析。然而,在像你这样的情况下,这是不可能的,但是例如ORMs在列表getter上使用它。例如,使用Hibernate,像这样的getter:

public List<Group> getGroups() {

可以通过Hibernate检查列表,以便它知道该列表应保存Group实例,从而相应地调整其查询。

(但是,即使泛型不是这样实现的,T也不是一个实例,它是一个类,写String instanceof String同样是错误的。应该是if(T.equals(String.class)))


非常感谢您的精彩解释,一旦SO允许,我将立即接受您的答案。 - user425367

1
public <T> T search(Class<T> clazz, String query){
 T returnValue = null;
 if (clazz==String.class){ }
 if (clazz==Integer.class){ }
 if (MyObject.clazz.isAssignableFrom(clazz){ }


String id = myObjcet.search(String.class, "select ...");

0

因为 T 在运行时被擦除了,它只存在于编译时。而 returnValue 是变量,它在运行时存在。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接