java.lang.Class.getInterfaces returns all directly implemented interfaces ie doesn't walk the class tree to get all interfaces of all parent types. eg For example the hierarchy
public interface A {}
public interface B {}
public interface C extends B {}
public class Foo implements A {} // Foo.class.getInterfaces() returns [A]
public class Bar implements C {} // Bar.class.getInterfaces() returns [C], note B is not included.
For Bar I would like to get [B, C], but for any arbitrary tree depth.
I could write this myself, but I'm sure a library must exist that does this already, any ideas?
Apache Commons Lang has method you need: ClassUtils.getAllInterfaces
Guava Solution:
final Set<TypeToken> tt = TypeToken.of(cls).getTypes().interfaces();
This is a much more powerful and cleaner reflection API than the ancient Apache stuff.
Don't forget, Spring Framework has many similar util classes like Apache Commons Lang. So there is: org.springframework.util.ClassUtils#getAllInterfaces
public interface A {}
public interface B {}
public interface E extends B{ }
public class C implements A{}
public class D extends C implements E{}
public class App {
public static void main(String[] args) {
final List<Class<?>> result = getAllInterfaces(D.class);
for (Class<?> clazz : result) {
System.out.println(clazz);
}
}
public static List<Class<?>> getAllInterfaces(Class<?> clazz) {
if (clazz == null) {
System.out.println(">>>>>>>>>> Log : null argument ");
return new ArrayList<>();
}
List<Class<?>> interfacesFound = new ArrayList<>();
getAllInterfaces(clazz, interfacesFound);
return interfacesFound;
}
private static void getAllInterfaces(Class<?> clazz,
List<Class<?>> interfacesFound) {
while (clazz != null) {
Class<?>[] interfaces = clazz.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
if (!interfacesFound.contains(interfaces[i])) {
interfacesFound.add(interfaces[i]);
getAllInterfaces(interfaces[i], interfacesFound);
}
}
clazz = clazz.getSuperclass();
}
}
}
Related
I wish to be able to get a List/ArrayList of N new instances from a static method inherited to subclasses so that I don't have to rewrite this same function in all subclasses.
I want to implement this so that I can build a vector containg some A and B. I've tried several methods but none of them worked for me :
public class Parent {
public static List<Parent> getNInstances(int n) {
List<Parent> out = new ArrayList<>();
for (int i = 0; i < n; i++) {
Parent newChildInstance = (Parent) MethodHandles
.lookup()
.lookupClass()
.getConstructor()
.newInstance()
out.add(newChildInstance);
}
}
}
I've got the MethodHandles thing from here since I feel like I need to get the class to be able to call .getConstructor().newInstance() which should, in theory, solve my problem. Nonetheless, this doesn't work, it gives me a NoSuchMethodException since he's not able to find the constructor from the Class given by
MethodHandles.lookup().lookupClass(), at least I think that's why.
Here is how I would like the method .getNInstances() to work.
public class Parent {
public Parent(){ }
public static List<Parent> getNInstances(int n) {
List<Parent> out = new ArrayList<>();
for (int i = 0; i < n; i++) {
Parent newChildInstance = ...
out.add(newChildInstance);
}
}
}
public class A extends Parent {
public A(){ }
}
public class B extends Parent {
public B(){ }
}
public class Main {
public static void main(String[] args) {
List<Parent> total = new ArrayList<>();
total.addAll(A.getNInstances(3));
total.addAll(B.getNInstances(4));
}
}
Here total should therefore be like [a, a, a, b, b, b, b] where a is an instance of A and b an instance of B, but by now, it's just empty.
There's no need at all to use reflection here. Use a factory and a method reference for the constructor.
This way you have compile-time assurance that the constructor you're trying to use actually exists.
abstract class ParentFactory
{
public List<Parent> getNInstances(int n)
{
final List<Parent> out = new ArrayList<>();
for (int i = 0; i < n; i++)
{
out.add(constructor().get());
}
return out;
}
protected abstract Supplier<Parent> constructor();
}
class AFactory extends ParentFactory
{
#Override
protected Supplier<Parent> constructor() {
return A::new;
}
}
class BFactory extends ParentFactory
{
#Override
protected Supplier<Parent> constructor() {
return B::new;
}
}
Sample usage:
List<Parent> total = new ArrayList<>();
total.addAll(new AFactory().getNInstances(3));
total.addAll(new BFactory().getNInstances(4));
I don't manage to reproduce your error.
But note some points :
1) Here, you will never lookup a class of the subclasses because lookupClass() returns the class that invoked the method and this is always Parent.getNInstances() :
Parent newChildInstance = (Parent) MethodHandles
.lookup()
.lookupClass()
.getConstructor()
.newInstance();
Make it an instance method will produce the same result.
2) Generic class should be enough to solve your problem and make it an instance method.
public class Parent<T extends Parent> {
public List<Parent> getNInstances(int n) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
List<Parent> out = new ArrayList<>();
for (int i = 0; i < n; i++) {
Class<T> clazz = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
Parent newChildInstance =
clazz.getConstructor().newInstance();
out.add(newChildInstance);
}
return out;
}
}
And subclasses :
public class A extends Parent<A> {
//...
}
public class B extends Parent<B> {
//...
}
Sample test :
List<Parent> total = new ArrayList<>();
total.addAll(new A().getNInstances(3));
total.addAll(new B().getNInstances(4));
System.out.println(total);
outputs :
[A#506e6d5e, A#96532d6, A#3796751b, B#67b64c45, B#4411d970,
B#6442b0a6, B#60f82f98]
Consider this example:
I have 3 interfaces: A, B, C, with methods a(), b(), c(); extending a base interface Intf;
I have a enum with options MyEnum.A, MyEnum.B, MyEnum.C;
I have a class extending this 3 interfaces: X implements A, B, C;
There is a way to implement a method in X like this;
public <T extends Intf> T getType (MyEnum enum)
and the result is the interface A, B or C, that is, accessing only method a(), b() or c()?
EDIT: I want to use it on a builder with fluent api:
X var = X.getType(MyEnum.A).a("value").build();
or
X var = X.getType(MyEnum.B).b("value").build();
but never
X var = X.getType(MyEnum.A).b("value").build(); //ERROR
You could dispatch the enum value, and return a matching instance, as #GhostCat suggested.
You could also invert the lookup, so each enum value provides an appropriate instance of Intf:
Variant 1: singleton instance per enum value
public enum MyEnum {
A(new AImpl()),
B(new BImpl()),
C(new CImpl());
private Intf instance;
MyEnum2(Intf instance) {
this.instance = instance;
}
public <T extends Intf> T getType() {
return (T) instance;
}
}
Variant 2: factory, creating new instances:
public enum MyEnum {
A(AImpl.class),
B(BImpl.class),
C(CImpl.class);
private Class<? extends Intf> type;
MyEnum(Class<? extends Intf> type) {
this.type = type;
}
public <T extends Intf> T getType() {
try {
return (T) type.newInstance();
} catch (InstantiationException | IllegalAccessException ex) {
throw new RuntimeException(ex.getMessage(), ex);
}
}
}
Usage:
A a = MyEnum.A.getType();
B b = MyEnum.B.getType();
C c = MyEnum.C.getType();
If I read your question correctly you want compile-time safety for
public <T extends Intf> T getType (MyEnum enum)
to return A for MyEnum.A, B for MyEnum.B etc.
You can achieve this compile-time safety if you make MyEnum class generic. This does now work with normal enums, but it works with old-fashioned "typesafe enum" pattern.
Assume we have three interfaces AA, BB , CC extending the base interface II:
public interface AA extends II { void a(); }
public interface BB extends II { void b(); }
public interface CC extends II { void c(); }
Now the class TT implements all of these interfaces:
public class TT implements AA, BB, CC {
#Override
public void a() { ... }
#Override
public void b() { ... }
#Override
public void c() { ... }
}
Now let EE be our generic pseudo-enum class, parameterized with some subtype of II:
public class EE<XX extends II> {
public static final EE<AA> A = new EE<AA>();
public static final EE<BB> B = new EE<BB>();
public static final EE<CC> C = new EE<CC>();
}
With these definitions the getType method can be declared as follows:
public <XX extends II> XX getType(EE<XX> enumVal)
This method may only return the type the type which parameterized the enumVal. Meaning
AA type = tt.getType(EE.A);
is valid but
BB type = tt.getType(EE.A);
is not.
One of the ways to implement the getType method would be delegate "conversion" of the TT instance to AA, BB or CC to the corresponding pseudo-enums:
public abstract class EE<XX extends II> {
public static final EE<AA> A = new EE<AA>() {
#Override
public <PP extends AA & BB & CC> AA convert(PP instance) {
return new AA() {
public void a() {
instance.a();
};
};
}
};
public static final EE<BB> B = new EE<BB>() {
#Override
public <PP extends AA & BB & CC> BB convert(PP instance) {
return new BB() {
public void b() {
instance.b();
};
};
}
};
public static final EE<CC> C = new EE<CC>() {
#Override
public <PP extends AA & BB & CC> CC convert(PP instance) {
return new CC() {
public void c() {
instance.c();
};
};
}
};
public abstract <PP extends AA & BB & CC> XX convert(PP instance);
}
You can also return instance directly, without wrapping in an anonymous inner class. But then the result can be force-casted to the other interfaces thus allowing access to other methods.
Finally, the implementation of getType is trivial:
public <XX extends II> XX getType(EE<XX> enumVal) {
return enumVal.convert(this);
}
From what I can see, the compiler won't allow
BB bb = tt.getType(EE.A);
Also
BB bb = (BB) tt.getType(EE.A);
bb.b();
won't work as in "produces ClassCastException in the runtime".
The disadvantages are a pseudo-enum construct and somewhat ugly implementation of convert.
Assuming that we are within class X, you have a local generic parameter, you could think of:
public <T extends Intf> T getType (MyEnum enumVal) {
if (enumVal == MyEnum.A) {
return (A) this;
if (enumVal == MyEnum.B) {
return (B) this;
But you don't gain anything from doing so. Those casts don't matter for the caller side.
Because there is nothing that the compiler could do for you here. You could write
A someA = whatever.getType(someEnum);
But you could as well write
B someB = whatever.getType(someEnum);
with the very same someEnum. And the compiler would be all happy.
If you want to achieve a gain on "compile time safety", you would have to somehow "connect" the argument type to the result type.
I have two classes A and B and they both have a common field in them, and I want to create a function in which if I pass Class A object then I want to set that common field value to the passed value and if I pass Class B object then I want to set that common field value to the passed value. Can anyone please tell me how can I do this, I am new to Java Generic Classes.
Otherwise I would have to make two different functions OR I would have to make an if and else which would decide that passed object belongs to which class ??
Class A
public class A{
int footer;
public void setFooter(int fo) {
footer = fo;
}
}
Class B
public class B{
int footer;
public void setFooter(int fo) {
footer = fo;
}
}
Class D
public class D{
public void change_footer(T generic_param, int value) {
generic_param.setFooter(value);
}
}
Class HelloWorld
public class HelloWorld{
public static void main(String []args){
Here I want to call
A a = new A();
new D().change_footer(a, 5);
B b = new B();
new D().change_footer(b, 5)
}
}
Thank You
And if I got all of the question wrong, and nor A nor B are generic, AND the type of field is fixed.
then you mean something like:
class D {
/*public <T extends Super> would be muuuch nicer here as well!*/
public /*static*/ <T> void change_footer(T obj, int data) {
//otherwise, you could just cast to Super...and set dat field.
if (obj instanceof A) {
((A) obj).setField(data);
} else if (obj instanceof B) {
((B) obj).setField(data);
} // else ... ?
}
}
Original answer:
Easy peasy (the "straight forward" implementation produces the desired results.):
class A<T> {
T daField;
public void setField(T pField) {
daField = pField;
}
public T getField() {
return daField;
}
}
class B<T> extends A {//empty
}
class Test {
public static void main(String... args) {
B<Object> testB1 = new B<>(); //
testB1.setField(new Object());
System.out.println(testB1.getField());
B<String> testB2 = new B<>();
testB2.setField("blah blah");
System.out.println(testB2.getField());
B<Integer> testB3 = new B<>();
testB3.setField(42);
System.out.println(testB3.getField());
}
}
System.out:
java.lang.Object#6d06d69c
blah blah
42
It get's (little) more complicated, when you want to instantiate Ts ...but still possible/other question. :)
Edit to your comment:
If there's only one common field, then why not:
/*abstract */class Super<T> {
T daField;
public void setField(T pField) {
daField = pField;
}
public T getField() {
return daField;
}
}
? ...and:
class A<T> extends Super { ... }
class B<T> extends Super { ... }
What is the most elegant way to iterate over all super classes/interfaces of a given Class<?> object? I am basically looking for a recursive getSuperclass() and getInterfaces() method, collecting the whole class hierarchy.
Lets assume our inheritance looks like follows (where Cn are classes and In are interfaces):
I3
↗ ↖
C2 I1 I2
↖ ↖ ↗
C1 I0
↖ ↗
C0
It should catch all classes displayed above. If possible, the iteration order should be breadth first, so something like this:
C0 -> C1 -> I0 -> C2 -> I1 -> I2 -> I3
Is there a built in method or a library providing creating a Collection<Class<?>>, Stream<Class<?>> or an Iterator<Class<?>>?
Any help is appretiated.
Given that you already seem to use Guava, here's a solution using Guava's Graph Traversal utilities.
public static Iterable<Class<?>> getClassHierarchy(Class<?> baseClass) {
return Traverser.forGraph(
(SuccessorsFunction<Class<?>>) node -> {
Class<?> superclass = node.getSuperclass();
List<Class<?>> interfaces = Arrays.asList(node.getInterfaces());
return superclass == null ? interfaces
: Iterables.concat(interfaces, Collections.singleton(superclass));
}
).breadthFirst(baseClass);
}
This solution implements an Iterator<Class<?>>. If you are OK with using libraries, I would recommend checking out the accepted answer.
public static class HierarchyIterator implements Iterator<Class<?>> {
private Queue<Class<?>> remaining = new LinkedList<>();
private Set<Class<?>> visited = new LinkedHashSet<>();
public HierarchyIterator(Class<?> initial) {
append(initial);
}
private void append(Class<?> toAppend) {
if (toAppend != null && !visited.contains(toAppend)) {
remaining.add(toAppend);
visited.add(toAppend);
}
}
#Override
public boolean hasNext() {
return remaining.size() > 0;
}
#Override
public Class<?> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Class<?> polled = remaining.poll();
append(polled.getSuperclass());
for (Class<?> superInterface : polled.getInterfaces()) {
append(superInterface);
}
return polled;
}
}
If you need a Collection<Class<?>>, you can use Google Guava for:
public static Set<Class<?>> getClassHierarchy(Class<?> forClass) {
Set<Class<?>> result = new LinkedHashSet<>();
Iterators.addAll(result, new HierarchyIterator(forClass));
return result;
}
calling:
System.out.println(getClassHierarchy(LinkedList.class));
yields
[class java.util.LinkedList, class java.util.AbstractSequentialList, interface java.util.List, interface java.util.Deque, interface java.lang.Cloneable, interface java.io.Serializable, class java.util.AbstractList, interface java.util.Collection, interface java.util.Queue, class java.util.AbstractCollection, interface java.lang.Iterable, class java.lang.Object]
I take your question more or less like a game, and I noticed that the breadth first requirement is not mandatory, so here is my solution.
It uses reflection.
It uses recursion.
It uses functional programming.
It is not very long.
It implements an internal iterator - forEach style.
You need Java 9 to compile it.
It is just a programming game :)
public class ClassIterator {
public void forEachSuperclasses(final Class<?> initialClass, final Consumer<Class<?>> action) {
generateStream(initialClass).distinct().forEach(action);
}
private Stream<Class<?>> generateStream(final Class<?> clazz) {
if (clazz == null) {
return Stream.empty();
}
return Stream.concat(
Stream.concat(Stream.of(clazz), generateStream(clazz.getSuperclass())),
Arrays.stream(clazz.getInterfaces()).flatMap(this::generateStream));
}
}
How to call it:
interface I3 {};
class C2 implements I3 {};
interface I1 extends I3 {};
interface I2 {};
class C1 extends C2 {};
interface I0 extends I0, I0 {};
class C0 extends C1 implements I0 {};
void testForEachSuperclasses() {
final ClassIterator iterator = new ClassIterator();
iterator.forEachSuperclasses(C1.class, System.out::println);
}
Output:
class com.example.classiterator.C0
class com.example.classiterator.C1
class com.example.classiterator.C2
class java.lang.Object
interface com.example.classiterator.I3
interface com.example.classiterator.I0
interface com.example.classiterator.I1
interface com.example.classiterator.I2
Here's another solution without external libraries, but which still works lazily and visits every class exactly once:
public static Iterable<Class<?>> getClassHierarchy(Class<?> baseClass) {
return () -> new Iterator<Class<?>>() {
private Class<?> nextValue;
private Queue<Class<?>> remaining = new LinkedList<>(Collections.singleton(baseClass));
private Set<Class<?>> visited = new HashSet<>();
#Override
public boolean hasNext() {
while (nextValue == null && !remaining.isEmpty()) {
Optional.ofNullable(remaining.poll())
.ifPresent((Class<?> type) -> {
visited.add(type);
Stream.concat(
streamOptional(Optional.ofNullable(type.getSuperclass())),
Arrays.stream(type.getInterfaces())
).filter(visited::add)
.forEach(remaining::offer);
nextValue = type;
});
}
return nextValue != null;
}
private <T> Stream<T> streamOptional(final Optional<T> optional) {
return optional.map(Stream::of).orElse(Stream.empty());
}
#Override
public Class<?> next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
Class<?> value = this.nextValue;
this.nextValue = null;
return value;
}
};
}
Note: writing this was a pain (in Java 8), because unfortunately, there is no Optional.stream() method and Stream.generate(supplier) can't be terminated so I couldn't use it.
Here is a quick Breadth First Hierarchy transverse:
public class ClassHierarchy {
private Queue<Class<?>> queue;
//a collection of "visited" classes,
//which is also the result of the search
private Set<Class<?>> visited;
public Set<Class<?>> getClassHierarchy(Class<?> cls){
visited = new LinkedHashSet<>(); //initialize visited log
bfs(cls);
return visited;
}
//breadth first traverse on hierarchy
private void bfs(Class<?> cls) {
if(cls == null){ return; }
queue = new LinkedList<>(); //initialize queue
queue.add(cls);
while (! queue.isEmpty()) {
cls = queue.poll();
//loop over super classes
for(Class<?> nextClass : getSuperClasses(cls)){
if((nextClass != null) && visited.add(nextClass)) {
queue.add(nextClass); //add class to the queue
}
}
}
return;
}
private List<Class<?>> getSuperClasses(Class<?> cls) {
List<Class<?>> superCs = new ArrayList<>();
superCs.addAll(Arrays.asList(cls.getInterfaces()));
superCs.add(cls.getSuperclass());
return superCs;
}
private boolean isVisited(Class<?> cls) {
return !(visited.add(cls));
}
public static void main(String[] args) {
ClassHierarchy ch = new ClassHierarchy();
System.out.println(ch.getClassHierarchy(LinkedList.class));
}
}
(Please check carefully. I did not have time yet to debug and improve. Will look at it later)
I was trying to understand how to avoid double entry in a clean and "designable" way to the following scenario:
public interface ICommandAble
{ }
public interface ILogAble extends ICommandAble
{ }
public interface IMonitorAble extends ICommandAble
{ }
public abstract class ClassAbs
{ }
public class A extends ClassAbs implements IMonitorAble, ILogAble
{ }
Test method:
public void test()
{
A a=new A();
List<ICommandAble>commandList=new ArrayList<ICommandAble>()
if (a instanceof ILogAble)
{
ILogAble logAbleItem=(ILogAble)a;
commandList.add(logAbleItem);
}
if (a instanceof IMonitorAble) {
IMonitorAble monitorAbleItem=(IMonitorAble)a;
commandList.add(monitorAbleItem);
}
for(ICommandAble item: commandList)
{
if(item instanceof IMonitorAble)
{
log.debug("is monitorable");
}
if(item instanceof ILogAble)
{
log.debug("is logable");
}
}
the output is:
2013-04-22 18:25:00,498 com... [DEBUG] is monitorable
2013-04-22 18:25:02,150 com.... [DEBUG] is logable
2013-04-22 18:25:08,322 com.... [DEBUG] is monitorable
2013-04-22 18:25:08,977 com.... [DEBUG] is logable
That will cause my program to do double executions for each "xAble"
I expected to see:
2013-04-22 18:25:00,498 com... [DEBUG] is monitorable
2013-04-22 18:25:02,150 com.... [DEBUG] is logable
How should I redesign this(in a clean way) that the second iterator conditionion will be based on the reference type and not on the instance type. getting something like this:
2013-04-22 18:25:00,498 com... [DEBUG] is monitorable
2013-04-22 18:25:02,150 com.... [DEBUG] is logable
Think that in the future I might have additional "ables"
Thanks,
ray.
If you are testing objects to see if they are instances of interfaces then they must implement that interface. They can always implement other interfaces too. In your scenario, to achieve the output you need you must make the objects only implement one of the two interfaces.
public class Test {
public interface ICommandAble {
}
public interface ILogAble extends ICommandAble {
}
public interface IMonitorAble extends ICommandAble {
}
public abstract class ClassAbs {
}
public class A extends ClassAbs implements IMonitorAble, ILogAble {
}
public class B extends ClassAbs implements IMonitorAble {
}
public class C extends ClassAbs implements ILogAble {
}
public void test() {
A a = new A();
B b = new B();
C c = new C();
List<ICommandAble> commandList = new ArrayList<ICommandAble>();
commandList.add(a); // Remove this line to just get the two printouts.
commandList.add(b);
commandList.add(c);
for (ICommandAble item : commandList) {
if (item instanceof IMonitorAble) {
System.out.println(item.getClass().getSimpleName() + " is monitorable");
}
if (item instanceof ILogAble) {
System.out.println(item.getClass().getSimpleName() + " is logable");
}
}
}
public static void main(String args[]) {
new Test().test();
}
}
prints
A is monitorable
A is logable
B is monitorable
C is logable
I have added an A to the list too to demonstrate the difference.
As you are only adding items to an List, you can change your code to verify if it is an instance of ICommandAble, like this:
if (a instanceof ICommandAble) {
commandList.add(a);
}
It's because your adding a into the commandList twice, once for being loggable and again for being monitorable.
You should combine the 2 if statements into 1:
if (a instanceof ILogAble || a instanceof IMonitorAble)
{
commandList.add(a);
}
Add the instances to a hashset not a list so that an instance would be present once even if it added more than once
As the other answers already explained, what you want is not possible with casting. You will need to use multiple lists. You can organize this lists in a Map to make it more maintainable, but maybe you should rethink your design.
Here a way how you could easily use multiple lists:
public interface ICommandAble {}
public interface ILogAble extends ICommandAble {}
public interface IMonitorAble extends ICommandAble {}
public abstract class ClassAbs {}
public class A extends ClassAbs implements IMonitorAble, ILogAble {}
public List<ICommandAble> getList(LinkedHashMap<Class<? extends ICommandAble>, List<ICommandAble>> commandList,
Class<? extends ICommandAble> clazz) {
if (commandList.get(clazz) != null)
return commandList.get(clazz);
ArrayList<ICommandAble> l = new ArrayList<>();
commandList.put(clazz, l);
return l;
}
public void test() {
A a = new A();
LinkedHashMap<Class<? extends ICommandAble>, List<ICommandAble>> commandList = new LinkedHashMap<>();
if (a instanceof ILogAble)
getList(commandList, ILogAble.class).add(a);
if (a instanceof IMonitorAble)
getList(commandList, IMonitorAble.class).add(a);
for (Class<? extends ICommandAble> clazz : commandList.keySet())
for (ICommandAble item : commandList.get(clazz)) {
if (clazz.equals(IMonitorAble.class))
log("is monitorable");
if (clazz.equals(ILogAble.class))
log("is logable");
}
}