繁体   English   中英

了解Java中的泛型语法-将多个接口实现为参数的泛型类型

[英]Understanding generics syntax in java - generic types implementing multiple interfaces as parameters

我有一些接口(为完整起见,还提供了两个虚拟类,因此您可以将代码复制到自己的ide中)

public interface ItfA
{
  String getA();
}

public interface ItfB
{
  String getB();
}

public class MyClassAdapter
{
    public Object getValue(Object bean)
    {
        return null; // override to do something useful
    }
}

public class MyClass
{
    public MyClass(MyClassAdapter mca)
    {
        // do something useful with it
    }
}

而且我有一些使用这些函数作为参数的函数(看起来有些怪异,但这就是我必须使用它们的方式(我无法更改MyClassAdapter ))...

public <T extends ItfA> MyClass getMyClass(final Class<T> itf)
{
    return new MyClass(new MyClassAdapter()
        {
            @Override
            public Object getValue(Object bean)
            {
                return itf.cast(bean).getA();
            }
        }
    );
}

所以我只能在实现接口ItfA类中调用此getMyClass否则编译器会抱怨。

或者,我可以不用命名泛型T来重写此方法为...

public MyClass getMyClass2(final Class<? extends ItfA> itf)
{
    return new MyClass(new MyClassAdapter()
        {
            @Override
            public Object getValue(Object bean)
            {
                return itf.cast(bean).getA();
            }
        }
    );
}

在某些情况下,我需要将类用作实现多个接口的参数-这将起作用:

public <T extends ItfA & ItfB> MyClass getMyOtherClass(final Class<T> itf)
{
    return new MyClass(new MyClassAdapter()
        {
            @Override
            public Object getValue(Object bean)
            {
                return itf.cast(bean).getA() + itf.cast(bean).getB();
            }
        }
    );
}

但这不起作用

public MyClass getMyOtherClass2(final Class<? extends ItfA & ItfB> itf)
{
    return new MyClass(new MyClassAdapter()
        {
            @Override
            public Object getValue(Object bean)
            {
                return itf.cast(bean).getA() + itf.cast(bean).getB();
            }
        }
    );
}

我没有得到这两种通用参数之间的区别(在方法名称之前使用<T extends ItfA>并在参数中使用Class<T>而不是在参数中使用Class<? extends ItfA> )-为什么两者都做类型只能在一个接口上使用,为什么一个可以在两个接口上使用,而另一个却不能。

有什么提示吗? 对我来说,第二个变种更具可读性,所以我更愿意这样做,但我不希望它与多个接口一起使用...

TypeParameter不同, TypeArgument不能有多个界限,所以<? extends ItfA & ItfB> <? extends ItfA & ItfB>无效。

这是我对为什么会这样的猜测。

我认为原因是TypeArgument需要特定才能有用。 例如,对于Class<T> ,方法cast返回T ,则您应该能够声明该类型的变量并将结果分配给它。

TypeArgument可以是:

  1. 类类别
  2. InterfaceType
  3. 的TypeVariable
  4. 数组类型
  5. 通配符

情况1-4没问题,那里总是有一些特定的类型或类型变量。

对于通配符,我们有WildcardBounds,例如<? extends IntfA> <? extends IntfA>

如果只允许一个上限,那么您就有T特定值。 如果是Class<? extends IntfA> Class<? extends IntfA>你可以假设cast返回InfA

如果允许多于一个上限<? extends ItfA & ItfB> <? extends ItfA & ItfB>那么问题是,那么您可以将T用于什么? 由于通常情况下您没有T任何特定类型,因此您能做的最好的事情是Object ,它不是很有用。

我认为这是语言作者没有为通配符类型参数分配多个上限的原因。

暂无
暂无

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

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