简体   繁体   English

Java通用方法约束-从约束中排除类型以防止擦除问题?

[英]Java generic method constraints - exclude type from constraint to prevent erasure problems?

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. ComponentTemplate是一个抽象类,而ConditionalComponent是一个接口。 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. 如果该组件实现ConditionalComponent ,则应使用其他方法来确定是否应添加特定组件。 A completely different approach is used when the object does not implement ConditionalComponent . 当对象不实现ConditionalComponent时,使用完全不同的方法。

The problem is that these methods have the same erasure (according to RAD, which of course refuses to compile this). 问题在于这些方法具有相同的擦除(根据RAD,当然会拒绝对此进行编译)。 Is there a way to define the first method such that it excludes any objects that extends both ComponentTemplate AND ConditionalComponent ? 有没有一种方法可以定义第一个方法,使其排除任何同时扩展ComponentTemplateConditionalComponent对象? 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? 我什至试图做的事还是有解决方法?

This is not allowed. 这是不允许的。 Why not? 为什么不?

When methods are called in Java, the method with the most specific type signiture is used. 在Java中调用方法时,将使用具有最特定类型签名的方法。

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. 我们可以调用G1 ,但是没有重定向就无法调用G2 We cannot downcast to A & B , only to either A or B . 我们不能贬低到A & B ,只能贬低到AB

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. A & B似乎并没有很好地集成到类型系统中(大多数人甚至都不知道),因此,在选择要分派给方法的哪个版本时,Java不会A A & B视为与A & B不同的类型。 。


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.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM