简体   繁体   English

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

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

I have some interfaces (and for completeness two dummy classes, so you may copy the code into your ide) 我有一些接口(为完整起见,还提供了两个虚拟类,因此您可以将代码复制到自己的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
    }
}

And I have some functions using these as parameters (looks a bit weird, but that's how I have to use them (I can't change the MyClassAdapter )) ... 而且我有一些使用这些函数作为参数的函数(看起来有些怪异,但这就是我必须使用它们的方式(我无法更改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();
            }
        }
    );
}

So I can call this getMyClass only with classes implementing interface ItfA - otherwise the compiler will complain. 所以我只能在实现接口ItfA类中调用此getMyClass否则编译器会抱怨。

Alternatively I can rewrite this method without the named generic type T as ... 或者,我可以不用命名泛型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();
            }
        }
    );
}

In some cases I need classes as parameters that implement more than one interface - this will work: 在某些情况下,我需要将类用作实现多个接口的参数-这将起作用:

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

but this one doesn't work 但这不起作用

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

I don't get the difference between these two kinds of generic parameters ( <T extends ItfA> before the method name and using Class<T> in the parameters opposed to using Class<? extends ItfA> in the parameters) - why do both types work with one interface, and why does one work with two interfaces, but the other one doesn't. 我没有得到这两种通用参数之间的区别(在方法名称之前使用<T extends ItfA>并在参数中使用Class<T>而不是在参数中使用Class<? extends ItfA> )-为什么两者都做类型只能在一个接口上使用,为什么一个可以在两个接口上使用,而另一个却不能。

Any hints? 有什么提示吗? To me, the second variant is a bit more readable, so I'd prefer that, but I don't get it to work with multiple interfaces ... 对我来说,第二个变种更具可读性,所以我更愿意这样做,但我不希望它与多个接口一起使用...

Unlike TypeParameter , TypeArgument can't have several bounds, so <? extends ItfA & ItfB> TypeParameter不同, TypeArgument不能有多个界限,所以<? extends ItfA & ItfB> <? extends ItfA & ItfB> is not valid. <? extends ItfA & ItfB>无效。

Here's my guess on why it is so. 这是我对为什么会这样的猜测。

I think the reason is that TypeArgument needs to be specific to be useful. 我认为原因是TypeArgument需要特定才能有用。 For instance in case of Class<T> the method cast returns T , you should be able to declare a variable of that type and assign the result to it. 例如,对于Class<T> ,方法cast返回T ,则您应该能够声明该类型的变量并将结果分配给它。

TypeArgument can be: TypeArgument可以是:

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

Cases 1-4 are not problematic, there you always have some specific type or type variable. 情况1-4没问题,那里总是有一些特定的类型或类型变量。

In case of the Wildcard we have WildcardBounds for instance <? extends IntfA> 对于通配符,我们有WildcardBounds,例如<? extends IntfA> <? extends IntfA> . <? extends IntfA>

If you allow just one upper bound, then you have something specific for T . 如果只允许一个上限,那么您就有T特定值。 In case of Class<? extends IntfA> 如果是Class<? extends IntfA> Class<? extends IntfA> you can assume that cast returns InfA . Class<? extends IntfA>你可以假设cast返回InfA

If you allow more that one upper bound <? extends ItfA & ItfB> 如果允许多于一个上限<? extends ItfA & ItfB> <? extends ItfA & ItfB> then the question is, what could you use for T then? <? extends ItfA & ItfB>那么问题是,那么您可以将T用于什么? Since you in general case you don't have any specific type for T , the best you can do is Object which is not very useful. 由于通常情况下您没有T任何特定类型,因此您能做的最好的事情是Object ,它不是很有用。

I think this is the reason language authors did not allo multiple upper bounds for wildcard type arguments. 我认为这是语言作者没有为通配符类型参数分配多个上限的原因。

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

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