测试对象是否实现接口


149

可能以前曾有人问过这个问题,但是快速搜索只提出了询问C#的相同问题。看这里。

我基本上想要做的是检查给定对象是否实现了给定接口。

我有点想出了一个解决方案,但这还不够舒适,无法在if或case语句中频繁使用它,我想知道Java是否没有内置解决方案。

public static Boolean implementsInterface(Object object, Class interf){
    for (Class c : object.getClass().getInterfaces()) {
        if (c.equals(interf)) {
            return true;
        }
    }
    return false;
}


编辑:好的,谢谢您的回答。特别是对于Damien Pollet和Noldorin,您让我重新考虑了设计,因此不再测试接口。


3
如果抛出一个异常,您是否不能尝试强制转换并捕获异常(或者,即使Java与C#“ as”运算符类似,也要检查是否为空)?我是C#编码器,而不是Java编码器,所以我主要是在这里猜测,尽管我认为这种方法在任何OO语言中都是可行的。
Noldorin

1
在这种情况下,只有在不必关心性能的情况下,抛出异常才是一种好习惯。
拉法2014年

1
请原谅,但是这些答案在哪里让您重新考虑设计?即使删除了,它们又是什么?您能帮我吗@sebastiangeiger
ozanmuyes

1
@ozanmuyes对不起,我4年没有写Java了,不幸的是我不记得自己做了什么。
sebastiangeiger

Answers:


191

instanceof运营商确实在工作NullPointerException安全的方式。例如:

 if ("" instanceof java.io.Serializable) {
     // it's true
 }

产生真实的。以来:

 if (null instanceof AnyType) {
     // never reached
 }

产生false,instanceof运算符是null安全的(您发布的代码不是)。

instanceofClass#isInstance(Object)的内置,编译时安全的替代方法


5
instanceof仅适用于类文字。因此不能在OP的情况下使用
LordOfThePigs

当然,这是编译时安全的;这是内置方式,也是问题(imho)的论点
dfa

@LordOfThePigs不,不是。它检查是否也实现了接口。
NimChimpsky 2014年

5
@NimChimpsky:您误解了我的观点。类文字是当你写的东西像MyClass.classMyInterface.class在源代码中。类文字可以引用类,接口和原始类型,并将返回相应的实例Class类。我的观点是,OP不是使用类文字,而是使用Class类的实例,不幸的是,instanceof关键字的右侧运算符必须是类文字,而不是Class类的实例。
LordOfThePigs

@dsdsdsdsd自从这篇文章以来,我什至没有听说过它,但是在Google上查找后,我发现它是Null Pointer Exception的缩写。
ozanmuyes

42

应该这样做:

public static boolean implementsInterface(Object object, Class interf){
    return interf.isInstance(object);
}

例如,

 java.io.Serializable.class.isInstance("a test string")

评估为true


8

我更喜欢instanceof

if (obj instanceof SomeType) { ... }

比这更常见,更易读 SomeType.isInstance(obj)


5
请记住,它if (obj instanceof SomeType) { ... }是静态的(也就是说-它在运行时不能更改),并且SomeType.isInstance(obj)是动态的。
Tomasz Bielaszewski 2013年


3

如果要测试接口:

public List<myType> getElement(Class<?> clazz) {
    List<myType> els = new ArrayList<myType>();
    for (myType e: this.elements.values()) {
        if (clazz.isAssignableFrom(e.getClass())) {
            els.add(e);
        }
    }
    return els;

}

clazz是一个接口,myType是一个您定义的类型,可以实现许多接口。通过此代码,您仅获得实现已定义接口的类型


1

今晚我在android上遇到了这个问题,在查看了javadoc解决方案之后,我想出了这个真正有效的解决方案,仅针对像我这样的人,他们需要的不仅仅是Javadoc的说明。

这是一个使用android java的实际接口的工作示例。在尝试强制转换AboutDialogListener字段之前,它将检查调用实现了AboutDialogListener接口的活动。

public class About extends DialogFragment implements OnClickListener,
    OnCheckedChangeListener {

public static final String FIRST_RUN_ABOUT = "com.gosylvester.bestrides.firstrunabout";


public interface AboutDialogListener {
    void onFinishEditDialog(Boolean _Checked);
}

private AboutDialogListener adl;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    Activity a = this.getActivity();
    if (AboutDialogListener.class.isInstance(a)) {
        adl = (AboutDialogListener) a;
        }
}

...稍后我在调用接口之前检查adl字段是否为!null

@Override
public void onStop() {
    super.onStop();
    sharedPref.edit().putBoolean(About.FIRST_RUN_ABOUT, _Checked).commit();
    // if there is an interface call it.
    if (adl != null) {
        adl.onFinishEditDialog(is_Checked());
    }
}

0

使用Apache commons-lang ArrayUtils,查看所需接口是否包含在对象的接口中

public static Boolean implementsInterface(Object object, Class interf){
    return ArrayUtils.contains(object.getClass().getInterfaces(), interf);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.