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

时间:2017-09-27 21:37:02

标签: java generics

我有一些接口(为了完整性,有两个虚拟类,所以你可以将代码复制到你的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))... < / p>

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();
            }
        }
    );
}

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

或者我可以在没有命名泛型类型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> ) - 为什么这两种类型都适用于一个界面,为什么一个界面使用两个界面,但另一个界面没有。

任何提示?对我来说,第二个变体更具可读性,所以我更喜欢这个,但我不能让它与多个接口一起工作......

1 个答案:

答案 0 :(得分:1)

http://www.thegeekstuff.com/2013/06/python-list不同,TypeParameter不能有多个边界,因此Class<T>无效。

这是我对为什么的猜测。

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

TypeArgument可以是:

  1. 类类别
  2. InterfaceType
  3. 的TypeVariable
  4. 数组类型
  5. 通配符
  6. 案例1-4没有问题,你总有一些特定的类型或类型变量。

    在通配符的情况下,我们有例如T的WildcardBounds。

    如果只允许一个上限,那么你有Class<? extends IntfA>特有的东西。如果是cast,您可以假设InfA返回<? extends ItfA & ItfB>

    如果您允许更多的那个上限T那么问题是,那么您可以使用T什么?由于您在一般情况下没有Object的任何特定类型,因此您可以做的最好的是{{1}},这不是很有用。

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