una que poo las interfaz interfaces implementacion herencia ejemplos clases clase caracteristicas abstractas abstracta java class jboss-arquillian

java - poo - Encuentre todas las clases e interfaces que una clase extiende o implementa recursivamente



public interface java (8)

De la pregunta ¿Cómo encuentras todas las subclases de una clase dada en Java? , this respuesta podría ser útil:

Usando la clase PojoClassImpl.java puede obtener la súper clase llamando al método getSuperClass() . Creo que eso es suficiente para que escribas un método recursivo.

Me preguntaba si había una manera fácil de determinar la lista completa de Tipos que una clase de Java extiende o implementa recursivamente.

por ejemplo:

class Foo extends Bar implements I1, I2 {...} class Bar implements I3 {...} interface I1 extends I4, I5 {...} interface I2 {...} interface I3 {...} interface I4 {...} interface I5 {...} class ClassUtil { public static Set<Class<?>> getAllExtendedOrImplementedTypesRecursively(Class<?> clazz){ ??? } } import static org.junit.Assert.*; public class ClassUtilTest { @Test public void shouldEqualClasses(){ Set<Class<?>> types = ClassUtil.getAllExtendedOrImplementedTypesRecursively(Foo.class); Set<Class<?>> checklist = new HashSet<>(); checklist.add(Foo.class); checklist.add(Bar.class); checklist.add(I1.class); checklist.add(I2.class); checklist.add(I3.class); checklist.add(I4.class); checklist.add(I5.class); assertTrue(checklist.containsAll(types)); assertTrue(types.containsAll(checklist)); } }

Creo que Arquillian ShrinkWrap creador ayuda.

ACTUALIZACIÓN: debido a que el objeto Clase no implementa Comparable> También necesito encontrar una forma de crear un Conjunto (o clase similar) sin implementar la interfaz Comparable (por ejemplo, depender únicamente del código hash del objeto de clase).

ACTUALIZACIÓN: cambió la prueba para usar hashset. derp


En java8

import java.util.Arrays; import java.util.Optional; import java.util.Set; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; public class ClassUtil { public static Set<Class<?>> getAllExtendedOrImplementedTypesRecursively(final Class<?> clazz) { return walk(clazz) .filter(Predicate.isEqual(java.lang.Object.class).negate()) .collect(Collectors.toSet()); } public static Stream<Class<?>> walk(final Class<?> c) { return Stream.concat(Stream.of(c), Stream.concat( Optional.ofNullable(c.getSuperclass()).map(Stream::of).orElseGet(Stream::empty), Arrays.stream(c.getInterfaces()) ).flatMap(ClassUtil::walk)); } }

Código de prueba:

import java.util.Set; class Test { public static void main(String[] args) { final Set<Class<?>> set = ClassUtil.getAllExtendedOrImplementedTypesRecursively(Foo.class); set.stream().map(Class::getName).forEach(System.out::println); } class Foo extends Bar implements I1, I2 {} class Bar implements I3 {} interface I1 extends I4, I5 {} interface I2 {} interface I3 {} interface I4 {} interface I5 {} }

Salida:

Test$Foo Test$Bar Test$I2 Test$I5 Test$I1 Test$I3 Test$I4


Es muy fácil, en caso de que tu clase sea Foo, tu código será así.

public void getClassDetails() { Class klass = Foo.class; Class<?> superKlass = klass.getSuperClass(); Class[] interfaces = klass.getInterfaces(); }


Hay un ClassUtils en el lenguaje común de Apache que tiene los 2 métodos que desea. .getAllSuperClasses () y .getAllInterfaces ().


La clave que desea está en el método Class#getSuperclass() :

public static Set<Class<?>> stuff(Class<?> target) { Set<Class<?>> classesInterfaces = new HashSet<>(); classesInterfaces.add(target); classesInterfaces.addAll(Arrays.asList(target.getInterfaces()); Class<?> superClass = target.getSuperclass(); if(superClass != null) classesInterfaces.addAll(stuff(superClass)); }


La siguiente implementación del método hace lo que requiere el OP, atraviesa la jerarquía de herencia para cada clase e interfaz:

public static Set<Class<?>> getAllExtendedOrImplementedTypesRecursively(Class<?> clazz) { List<Class<?>> res = new ArrayList<>(); do { res.add(clazz); // First, add all the interfaces implemented by this class Class<?>[] interfaces = clazz.getInterfaces(); if (interfaces.length > 0) { res.addAll(Arrays.asList(interfaces)); for (Class<?> interfaze : interfaces) { res.addAll(getAllExtendedOrImplementedTypesRecursively(interfaze)); } } // Add the super class Class<?> superClass = clazz.getSuperclass(); // Interfaces does not have java,lang.Object as superclass, they have null, so break the cycle and return if (superClass == null) { break; } // Now inspect the superclass clazz = superClass; } while (!"java.lang.Object".equals(clazz.getCanonicalName())); return new HashSet<Class<?>>(res); }

JFrame.class con JFrame.class y obtuve lo siguiente:

Set<Class<?>> classes = getAllExtendedOrImplementedTypesRecursively(JFrame.class); for (Class<?> clazz : classes) { System.out.println(clazz.getName()); }

Salida:

java.awt.Container java.awt.Frame javax.swing.JFrame javax.swing.TransferHandler$HasGetTransferHandler java.awt.Window javax.accessibility.Accessible javax.swing.RootPaneContainer java.awt.Component javax.swing.WindowConstants java.io.Serializable java.awt.MenuContainer java.awt.image.ImageObserver

ACTUALIZACIÓN: Para el caso de prueba del OP se imprime:

test.I5 test.Bar test.I2 test.I1 test.Foo test.I3 test.I4


Si entendí bien tu pregunta, quieres encontrar todas las superclases (clase e interfaz) de una clase específica. Si es así puedes consultar la siguiente solución.

para encontrar las superclases

Class C = getClass(); while (C != null) { System.out.println(C.getSimpleName()); C = C.getSuperclass(); }

para encontrar las interfaces

C = getClass(); for(Class adf: C.getInterfaces()){ System.out.println(adf.getSimpleName()); }


Una vez implementé un mecanismo similar usando asm en alguna rama de ShrinkWrap https://github.com/mmatloka/shrinkwrap/commit/39d5c3aa63a9bb85e6d7b68782879ca10cca273b . El problema es que a veces la clase puede usar un objeto que es una implementación de interfaz que no se menciona en otro archivo, por lo que aún puede fallar durante la implementación.

Por lo que sé hace un tiempo, la posición oficial era más bien no incluir esa característica dentro de ShrinkWrap , sino confiar en herramientas, por ejemplo, en JBoss Tools , donde debería haber una característica que permita adiciones de clases recursivas.