Java:帮助我理解:如何在有界通配符字段上使用接口方法? [英] Java: Help me understand: How to use interface methods on a bounded wildcard field?

查看:233
本文介绍了Java:帮助我理解:如何在有界通配符字段上使用接口方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

  class SomeClass {} 

类DerivedClass extends SomeClass {}

接口IInterf< T扩展SomeClass> {
T returnsT();
void paramT(T parm);
T paramAndReturnT(T parm);
int nonGenericMethod(int x);
}

class Impl {
protected IInterf<?>领域; //这被绑定到< extends SomeClass>
// - 它被绑定
//的IInterf定义
//所隐含,但这有什么意义?

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

public void doSmth(){

SomeClass sc = field.returnsT(); //作品

field.paramT(new SomeClass());
//错误:接口IInterf中的方法参数< T>不能应用于给定的类型;
//必需:CAP#1
//发现:SomeClass
// reason:实际参数SomeClass不能通过方法调用转换转换为CAP#1
// where T是一个类型变量:
// T扩展了在接口IInterf
中声明的SomeClass //其中CAP#1是一个新的类型变量:
// CAP#1从捕获?

field.paramT(null); //作品

SomeClass sc2 = field.paramAndReturnT(new DerivedClass());
//错误:接口IInterf中的方法paramAndReturnT< T>不能应用于给定的类型;
// SomeClass sc2 = field.paramAndReturnT(new DerivedClass()); // required:CAP#1
// found:DerivedClass
// reason:实际参数DerivedClass不能通过方法调用转换转换为CAP#1
//其中T是一个type-变量:
// T扩展在接口IInterf
中声明的SomeClass //其中CAP#1是一个新的类型变量:
// CAP#1从捕获?
//
int x = field.nonGenericMethod(5); //显然有效。






$ b

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



我错过了什么吗?

解决方案当您将字段声明为

时,

 受保护的IInterf<?>领域; 

代表一个未知的类,扩展 SomeClass 。把它看作不是通配符,而是作为一个派生 SomeClass 但匿名的特殊类。



如果你现在尝试调用

  field.paramT(new SomeClass()); 

失败是因为 SomeClass 实例不是与所代表的内容兼容,即扩展 SomeClass

的匿名类

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

完全相同 $ b

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


I'm having trouble understanding why I can use bounded wildcards like this, if I can't (seem to) make any (genericly-typed) use of it.

If I have a wildcard field in a class, I can't use any of the methods with generic parameters of the implemented interface (unless I supply null as the argument).

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, I couldn't convince the C# compiler to accept something similar.

Am I missing something?

解决方案

When you declare field as

protected IInterf<?> field;

the ? stands for an unknown class that extends SomeClass. Think of it not a s a wildcard but as a particular class deriving SomeClass but anonymous.

If you now try to call

field.paramT(new SomeClass());

this fails because a SomeClass instance is not compatible to what the ? is standing for, namely the anonymous class that extends SomeClass.

There is no problem to use null, this is compatible with any class.

Exactly the same happens with

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

这篇关于Java:帮助我理解:如何在有界通配符字段上使用接口方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆