检查通用类型 T 是否实现了一个接口。

32

我有一个Java类:

public class Foo<T>{
}

在这个类中,我希望知道T是否实现了某个接口。

以下代码并不起作用,但它是我想要实现的思路:

if(T.class implements SomeInterface){
    // do stuff
}

我想检查传递给Foo的类T在其签名上是否implements SomeInterface

这可能吗?怎么做?

3个回答

63

奇怪的是,泛型在接口上也使用了 extends 关键字。1 你应该这样使用:

public class Foo<T extends SomeInterface>{
    //use T as you wish
}

这实际上是实施的要求,不是真正的真/假检查。

对于一个真/假检查,请使用无界泛型(class Foo<T>{)并确保您获得一个 Class<T>,使您拥有一个可识别的类型:

if(SomeInterface.class.isAssignableFrom(tClazz));

其中tClazz是一个类型参数为java.lang.Class<T>的参数。

如果您获得了一个可靠类型的参数,那么它就仅仅是:

if(tParam instanceof SomeInterface){

但是仅使用通用声明无法实现此目的。

1如果您想要求扩展一个类和多个接口,可以按照以下方式操作:<T extends FooClass & BarInterface & Baz> 类(仅限一个,因为Java中没有多继承)必须放在 首位,其后任何接口均可以任意顺序排列。


1
嗨,我真的需要进行真/假检查,因为我正在修改一个现有的类。我正在尝试您的第二段代码,但仍然不确定tClass从哪里来。对此有任何帮助吗? - Budius
1
@Budius,您的用户需要在某个时候传递someInstanceOfT.getClass()Class <T>或直接传递T的实例。否则,类型擦除将不允许您获取它。 - nanofarad
1
因此我不能使用实际的通用 T 来测试接口,我只能在 public void add(T object){...} 中使用它,并在 object 上进行测试。 - Budius
1
确实很遗憾,我不确定它是否符合我的要求,因为我需要在构造函数中生成文件名。您能想到其他获取可能的SerializableserialVersionUID的方法吗? - Budius
好的,我想最后我被救了。最初创建这个类的人创建了一个 public abstract Class<T> myclass();,所以我可以使用 instanceof。再次感谢。 - Budius
理解class<? extends myInterface>是我这种情况下类函数参数的正确语法比应该更难。感谢详细的解释! - slycrel

4
你可以使用 isAssignableFrom 来检查它。
if (YourInterface.class.isAssignableFrom(clazz)) {
    ...
}

或者获取接口数组为
Class[] intfs = clazz.getInterfaces();

OP需要一个可靠的类型来获取clazz,可能需要接受Class<T>作为参数或在构造函数中。 - nanofarad

0

使用 isAssignableFrom()

isAssignableFrom()方法确定由该Class对象表示的类或接口是与指定的Class参数表示的类或接口相同,或者是其超类或超接口。

if (SomeInterface.class.isAssignableFrom(T class)) {
  //do stuff
}

不起作用,类型擦除。而且 T Class object 不是有效的语法。你是指 t 的实例吗? - nanofarad
@hexafraction 修改了我的答案。 - Naveen Kumar Alone

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