问题
I have a class called X that implements multiple (e.g. 3) interfaces, call them A, B and C.
I create another interface AB that extends interface A and B.
How can I use reflection to create an instance of X that is assignable to interface AB?
I keep getting ClassCast exceptions with this code:
package test.messages;
public interface A
{
void methodA();
}
package test.messages;
public interface B
{
void methodB();
}
package test.messages;
public interface C
{
void methodC();
}
package test.messages;
public interface AB extends A, B
{
}
package test.messages;
public class X implements A, B, C
{
@Override
public void methodC()
{
System.out.println("C");
}
@Override
public void methodB()
{
System.out.println("B");
}
@Override
public void methodA()
{
System.out.println("A");
}
}
Then in a completely different class:
AB api = (AB)Class.forName("test.messages.X").newInstance();
System.out.println(api);
Now when I try with just one interface, say A, it works fine.
Is there anyway to get it to work with the combined interface AB?
回答1:
What you really want is AND type -- A&B. This is generally not supported in Java. However, we could create a wrapper class that contains a value that is both type A and type B. (It seems that every problem can be solved by a wrapper:)
public class AB<T extends A&B>
{
public final T v;
...
v = (T)Class.forName("test.messages.X").newInstance();
}
Instead of using type A&B, we use AB<?> everywhere it's needed. We'll operate on its field v, which is both A and B.
void foo(AB<?> ab)
{
ab.v.methodOfA();
ab.v.methodOfB();
}
Or you could make AB a subtype of A and B too.
public class AB<T extends A&B> implements A, B
{
public final T v;
@Override // A
public int methodOfA(){ return v.methodOfA(); }
See more at https://stackoverflow.com/a/32659085/2158288
回答2:
The is-a relationship doesn't work that way. The fact that AB implements A and B and X implements A and B doesn't make X assignable to AB.
Even if you could think that AB is compatible with any type that implements A and B that's not the case as AB is a different type and the hierarchy tree in Java is fixed with the definition of the classes themselves.
Think about the Liskov substitution principle: if you add a method to AB then X is not a valid candidate anymore since it wouldn't contain the method declared in AB.
You would need a programming language that supports a structural type system to do it.
回答3:
You can't do that because in the inheritance tree X does not implement AB. If A,B,C are all interfaces a easy way to fix the problem is to say that X implements AB,C which that means it can be cast as A, as B, as C and as AB.
来源:https://stackoverflow.com/questions/34729711/java-multiple-interfaces-and-reflection