Java通用方法约束 - 从约束中排除类型以防止擦除问题? [英] Java generic method constraints - exclude type from constraint to prevent erasure problems?

查看:100
本文介绍了Java通用方法约束 - 从约束中排除类型以防止擦除问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图基于类型约束重载一个方法。代码如下所示:

  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 是一个抽象类,并且 ConditionalComponent 是一个接口。这两种方法可以将组件添加到组件列表中。在组件实现 ConditionalComponent 的情况下,应该使用其他方法来确定是否应添加特定组件。当对象没有实现 ConditionalComponent



时会使用完全不同的方法。问题是这些方法具有相同的擦除(根据RAD,当然拒绝编译这个)。有没有办法定义第一个方法,使它排除 ComponentTemplate AND ConditionalComponent ?我想象了这样的事情:

  protected static< T extends ComponentTemplate 
& !ConditionalComponent> void addComponent(List< ComponentTemplate> factors,T component)
{
...
}

但当然,这不起作用(这不是有效的语法)。是我试图做甚至可能的,还是有解决方法?

解决方案

这是不允许的。为什么不呢?



当在Java中调用方法时,会使用具有最具体类型签名的方法。



在这个例子中:

 接口A {...} 
接口B {...}
class X extends A,B {...}

void f(X);
void f(A);
void f(B);

X x = ...
f(x); //调用f(X)
f((A)x); //调用f(A)
f((B)x); //调用f(B)

我们都知道如何转换以调用我们想要的正确方法。

但在例子中,

 < T extends X> void g(T); // G1 

g(x); //调用G1

我们可以调用 G1 ,但无法在不进行重定向的情况下调用 G2
我们不能贬低为 A& B ,只限于 A B



A& B 似乎没有很好地整合到类型系统中(大多数人甚至不知道它),因此Java不会将 A 看作是与 A& B






更多疯狂的例子:

 接口A 
接口B扩展A

< T扩展A& B个void f(T)
< T扩展B> void f(T)

这会编译,但你不能调用其中任何一个

  B b = new B(){...} 
f(B); //方法引用是不明确的。


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?

解决方案

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.

这篇关于Java通用方法约束 - 从约束中排除类型以防止擦除问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆