0

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

如果我在一个类中有一个通配符字段,我就不能使用任何带有已实现接口的通用参数的方法(除非我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# 编译器接受类似的东西。

我错过了什么吗?

4

3 回答 3

1

当您声明field

protected IInterf<?> field;

代表扩展的?未知类SomeClass。不要把它想象成一个通配符,而是一个特定的类派生SomeClass但匿名。

如果你现在尝试打电话

field.paramT(new SomeClass());

这失败了,因为一个SomeClass实例与它所代表的不兼容?,即扩展的匿名类SomeClass

使用没有问题null,这与任何类都兼容。

完全相同的情况发生

SomeClass sc2 = field.paramAndReturnT(new DerivedClass());
于 2013-01-12T16:03:35.033 回答
0

You're trying to use generics/wildcards where they are not needed. Instead, either of the following will work:

1) Define the interface so that it accepts any class, and limit the types when using the interface:

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

2) Define the interface so that it accepts classes that extend SomeClass, and use the interface without specifying extra type information:

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

As for why the wildcard does not work: ? extends SomeClass means an unknown subtype of SomeClass. Since we don't know what the type is, we don't know if it is a supertype of SomeClass (or DerivedClass in the second method call); it might or might not be such a supertype, so it isn't safe to pass SomeClass (or DerivedClass). (from the Java Wildcards documentation)

于 2013-01-12T16:15:24.997 回答
0

你是对的,你不能使用这些方法。通常,您不需要这些方法(例如,您将某些内容添加<? extends T>到集合<T>中。如果您不需要更多信息,则使用它们是有意义的。如果您需要调用这些方法,则不能使用通配符。相反,您可以这样做<T extends SomeClass>

于 2013-01-12T16:03:39.320 回答