Java的:帮助我了解:如何使用上界通配符场接口中的方法?(Java: Help me unders

2019-10-30 23:39发布

我无法理解为什么我可以使用通配符有限像这样的,如果我没有(似乎)可以使任何(genericly类型的)使用它。

如果我在一个班有一个通配符场,我不能使用任何与实现的接口的泛型参数的方法(除非我提供null作为参数)。

class SomeClass {}

class DerivedClass extends SomeClass {}

interface IInterf<T extends SomeClass> {
    T returnsT();
    void paramT(T parm);
    T paramAndReturnT(T parm);
    int nonGenericMethod(int x);
}

class Impl {
    protected IInterf<?> field; //this is bound to <extends SomeClass>
                                //- it's implied by the definition 
                                //  of IInterf which is bound
                                // but what's the point?

    public Impl(IInterf<? extends SomeClass> var){
        field = var;
    }
    public void doSmth(){

        SomeClass sc = field.returnsT();  //works

        field.paramT(new SomeClass());
          //error: method paramT in interface IInterf<T> cannot be applied to given types;
          //required: CAP#1
          //found: SomeClass
          //reason: actual argument SomeClass cannot be converted to CAP#1 by method invocation conversion
          //where T is a type-variable:
          //  T extends SomeClass declared in interface IInterf
          //where CAP#1 is a fresh type-variable:
          //  CAP#1 extends SomeClass from capture of ? 

         field.paramT(null); //works

        SomeClass sc2 = field.paramAndReturnT(new DerivedClass());
          //error: method paramAndReturnT in interface IInterf<T> cannot be applied to given types;
          // SomeClass sc2 = field.paramAndReturnT(new DerivedClass());           //required: CAP#1
          //found: DerivedClass
          //reason: actual argument DerivedClass cannot be converted to CAP#1 by method invocation conversion
          //where T is a type-variable:
          //  T extends SomeClass declared in interface IInterf
          //where CAP#1 is a fresh type-variable:
          //  CAP#1 extends SomeClass from capture of ?            
          //
        int x = field.nonGenericMethod(5);  //obviously works.
    }
}

FWIW,我无法说服C#编译器接受类似的东西。

我缺少的东西吗?

Answer 1:

当你声明field

protected IInterf<?> field;

? 代表扩展一个未知的类SomeClass 。 想到这不是ASA通配符但作为一个特定的类派生SomeClass ,但匿名。

如果您现在试图调用

field.paramT(new SomeClass());

失败的原因是一个SomeClass实例不是什么兼容? 是站在了,即扩展了匿名类SomeClass

有没有用的问题null ,这是与任何兼容类。

正是同样的情况与

SomeClass sc2 = field.paramAndReturnT(new DerivedClass());


Answer 2:

你是对的,你不能使用这些方法。 通常情况下,你不需要这些方法(例如,你添加了一些<? extends T>的集合<T>这是有道理的,如果你并不需要了解更多信息使用它们。如果你需要调用这些方法,您不能使用通配符。相反,你可以做<T extends SomeClass>



Answer 3:

您正在尝试使用并不需要它们的地方泛型/通配符。 相反,无论是下面方法:

1)定义的接口,以便它接受任何类,并限制类型使用界面时:

interface IInterf<T> {}
protected IInterf<SomeClass> field;

2)定义的接口,以便它接受扩展类SomeClass ,并使用该接口不指定额外的类型信息:

interface IInterf<T extends SomeClass> {}
protected IInterf field;

至于为什么通配符不起作用: ? extends SomeClass ? extends SomeClass装置的一个未知的亚型SomeClass 。 因为我们不知道是什么类型,我们不知道它是一个超SomeClass (或DerivedClass在第二个方法调用); 它可能会或可能不会是这样一个超类,所以它是不是安全通过SomeClass (或DerivedClass )。 (从Java的通配符文档 )



文章来源: Java: Help me understand: How to use interface methods on a bounded wildcard field?