问题
I am trying to overload a method based on type constraints. The code looks something like this:
protected static <T extends ComponentTemplate> void addComponent(List<ComponentTemplate> factors, T component)
{
...
}
protected static <T extends ComponentTemplate
& ConditionalComponent> void addComponent(List<ComponentTemplate> factors, T conditionalComponent)
{
....
}
ComponentTemplate
is an abstract class, and ConditionalComponent
is an interface. These two methods can add a component to a list of components. In the case that the component implements ConditionalComponent
, there will be additional methods that should be used to determine if the specific component should be added. A completely different approach is used when the object does not implement ConditionalComponent
.
The problem is that these methods have the same erasure (according to RAD, which of course refuses to compile this). Is there a way to define the first method such that it excludes any objects that extends both ComponentTemplate
AND ConditionalComponent
? I imagined something like this:
protected static <T extends ComponentTemplate
& !ConditionalComponent> void addComponent(List<ComponentTemplate> factors, T component)
{
...
}
But of course, that doesn't work (it's not valid syntax). Is what I'm trying to do even possible, or is there a work-around?
回答1:
This is not allowed. Why not?
When methods are called in Java, the method with the most specific type signiture is used.
In the example:
interface A {...}
interface B {...}
class X extends A, B {...}
void f(X);
void f(A);
void f(B);
X x = ...
f(x); // calls f(X)
f((A)x); // calls f(A)
f((B)x); // calls f(B)
We all know how to cast to call the correct method we want.
But in the example
<T extends X> void g(T); //G1
<T extends A & B> void g(T); //G2
g(x); // calls G1
We can call G1
, but there is no way to call G2
without redirection.
We cannot downcast to A & B
, only to either A
or B
.
The A & B
does not seem well intgrated into the type system (most people won't even know of it), therefore Java does not see A
as being a different type from A & B
when choosing which version of a method to dispatch to.
Futher examples of madness:
interface A
interface B extends A
<T extends A & B> void f(T)
<T extends B> void f(T)
This will compile, but you can't call either of them
B b = new B(){...}
f(B); // method reference is ambiguious.
来源:https://stackoverflow.com/questions/23392586/java-generic-method-constraints-exclude-type-from-constraint-to-prevent-erasur