Określ, czy klasa implementuje interfejs w języku Java


92

Mam Classprzedmiot. Chcę ustalić, czy typ, który Classreprezentuje obiekt, implementuje określony interfejs. Zastanawiałem się, jak można to osiągnąć?

Mam następujący kod. Zasadniczo pobiera tablicę wszystkich klas w określonym pakiecie. Następnie chcę przejść przez tablicę i dodać obiekty Class, które implementują interfejs do mojej mapy. Problem polega na tym, że isInstance()przyjmuje obiekt jako parametr. Nie mogę utworzyć instancji interfejsu. Więc jestem z tym trochę zagubiony. Jakieś pomysły?

Class[] classes = ClassUtils.getClasses(handlersPackage);
for(Class clazz : classes)
{
    if(clazz.isInstance(/*Some object*/)) //Need something in this if statement
    {
        retVal.put(clazz.getSimpleName(), clazz);
    }
}

Odpowiedzi:


215

Powinieneś użyć isAssignableFrom:

if (YourInterface.class.isAssignableFrom(clazz)) {
    ...
}

Działa to, jeśli projekt jest taki sam. Ale jeśli skopiujesz kod interfejsu 1: 1, stworzysz nowy projekt i jar, a następnie spróbujesz załadować ten jar jako wtyczkę, wywołanie zwróci false. Porównując według nazwy, a następnie „prac”, jak napisał Roddy. Ale nie mam pojęcia, jak to sprawdzić w sposób, w jaki Java ostatecznie weryfikuje zgodność. Z nazwy to brudne podejście. Twój jest w porządku, oczywiście, jeśli projekt jest taki sam. ................ MOŻE robię to źle: tworzę instancję URLClassLoader dla pliku wtyczki i ładuję ją w ten sposób. Może powinienem wypróbować program ładujący innej klasy.
Prezydent Dreamspace

4
Masz problemy z ładowaniem zajęć. Jeśli załadujesz tę samą klasę dwukrotnie za pomocą różnych programów ładujących klasy, te dwie Classinstancje nie będą kompatybilne. Możesz zobaczyć błędy, takie jak java.lang.ClassCastException: com.my.CustomClass cannot be cast to com.my.CustomClasslub coś podobnie niewytłumaczalnego.
Flavio,

Do tej pory wypróbowałem różne podejścia i ostatecznie okazało się, że główny problem jaki miałem był taki: podczas gdy interfejs w mojej wtyczce i głównym projekcie były identyczne, to nie były w tym samym miejscu, więc przestrzeń nazw / adres był inny. . Btw, jestem teraz przy użyciu: myClassLoader = new URLClassLoader(new URL[] { candidateFile.toURI().toURL() }, LoadedPlugin.class.getClassLoader());a classToLoad = Class.forName("com.blablabla.plugin.Main", true, myClassLoader);i instance = (MyIntf) classToLoad.newInstance();działa jak czar.
Prezydent Dreamspace

17

możesz użyć poniższej funkcji, aby uzyskać wszystkie zaimplementowane interfejsy

Class[] intfs = clazz.getInterfaces();

10

Możesz użyć, class.getInterfaces()a następnie sprawdzić, czy klasa interfejsu jest tam.

Class someInterface; // the interface you want to check for 
Class x; // 
Class[] interfaces = x.getInterfaces();

for (Class i : interfaces) {
    if (i.toString().equals(someInterface.toString()) {
        // if this is true, the class implements the interface you're looking for
    }
}

Podejście to sprawdzi się technicznie, ale o wiele prostszym i czystszym podejściem jest użycie, isAssignableFromjak wspomina Flavio.
jwj

Tak, to prawda, chociaż twoja odpowiedź była głosowana więcej niż kilka razy i pomyślałem, że warto dodać jakiś kontekst. Chociaż używanie isAssignableFromjest prawdopodobnie preferowane, mogą wystąpić przypadki, w których trzeba będzie przejrzeć listę interfejsów implementowanych przez klasę, patrząc na nazwy.
jwj

W rzeczywistości to nie działa, getInterfaces () działa tylko wtedy, gdy klasa implementuje interfejs bezpośrednio, jeśli nadklasa implementuje interfejs lub superinterfejs rozszerza go, ten interfejs nie zostanie zwrócony przez getInterfaces (). Musisz przejść przez drzewo wszystkich superklas i interfejsów, aby uzyskać wszystkie interfejsy implementowane przez klasę.
James Roper,

To nie było jednak pytanie.
Roddy of the Frozen Peas

1

Możesz też ustawić instancję, dodając „.class”

Class[] classes = ClassUtils.getClasses(handlersPackage);
for(Class clazz : classes)
{
    if(Interface.class.isAssignableFrom(clazz))
    {
        retVal.put(clazz.getSimpleName(), clazz);
    }
}

2
Każdy, kto patrzy na to podejście, powinien rozważyć odpowiedź Flavio. Zwróć uwagę, że kod w tym przykładzie robi kilka rzeczy, które mogą nie mieć natychmiastowego sensu: ClassUtilsnie jest częścią Javy (jest w Guava, Spring i innych frameworkach), termin Interfaceużyty powyżej ma odnosić się do konkretnego testowanego interfejsu ( tj. nie jest to słowo kluczowe Java w tym kontekście), a cel funkcji retValnie jest nigdzie wyjaśniony ani wymieniony.
jwj
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.