了解上限和下限?在Java泛型中

Lit*_*ild 31 java generics subclass superclass

我真的很难理解外卡参数.我有几个问题.

  1. ?作为类型参数只能在方法中使用.例如:printAll(MyList<? extends Serializable>)我无法使用?类型参数定义类.

  2. 我理解上限?. printAll(MyList<? extends Serializable>)意思是:" 如果它有实现接口的对象,printAll将打印.MyListSerialzable "
    我有一个问题super.printAll(MyList<? super MyClass>)意思是:" 如果它有对象或任何扩展的类(后代),printAll将打印.MyListMyClassMyClassMyClass "

在我出错的地方纠正我.

总之,只有TEKVN可以用作类型参数用于定义通用类.?只能用于方法


更新1:

public void printAll(MyList<? super MyClass>){
    // code code code
}
Run Code Online (Sandbox Code Playgroud)

根据Ivor Horton的书,MyList<? super MyClass>意味着MyList如果它具有MyClass它实现的对象或任何接口或类,我可以打印.也就是说,MyClass是一个下限.它是继承层次结构中的最后一个类.这意味着我最初的假设是错误的.

所以,如果MyClass看起来像:

public class MyClass extends Thread implements ActionListener{
    // whatever
}
Run Code Online (Sandbox Code Playgroud)

然后,printAll()将打印如果
1. MyClass列表中
有对象2.有对象ThreadActionListenerList


更新2:

所以,在阅读了问题的许多答案后,我的理解是:

  1. ? extends T任何延伸的类T.因此,我们指的是儿童T.因此,T是上限.继承层次结构中最上层的类

  2. ? super T任何类/接口是superT.因此,我们指的是所有的父母T.T因此是下限.继承层次结构中最低级的类

Pau*_*ora 17

?作为类型参数只能在方法中使用.例如:printAll(MyList<? extends Serializable>)我无法使用?类型参数定义类.

wildcard(?)不是形式类型参数,而是可以用作类型参数.在你给的例子,? extends Serializable给出一个类型参数的泛型类型MyList,该的printAll方法的参数.

方法也可以声明像类这样的类型参数,例如:

static <T extends Serializable> void printAll(MyList<T> myList)
Run Code Online (Sandbox Code Playgroud)

我理解上限?.printAll(MyList<? extends Serializable>)表示printAll将打印MyList,如果它具有实现Serialzable接口的对象

更准确地说,它意味着只有在传递一个带有或实现的泛型类型的情况下才会编译调用printAllMyListSerializable.在这种情况下,它会接受MyList<Serializable>,MyList<Integer>等等.

我有点问题super.printAll(MyList<? super MyClass>)表示printAll将打印MyList,如果它有MyClass对象或任何扩展MyClass的类(MyClass的后代)

与之界限的通配符super下限.所以我们可以说一个调用printAll只有在传递一个MyList泛型类型MyClass或某些超类型的情况下才会编译MyClass.所以在这种情况下,它会接受MyList<MyClass>,例如MyList<MyParentClass>,或MyList<Object>.

所以,如果MyClass看起来像:

public class MyClass extends Thread implements ActionListener{
    // whatever
}
Run Code Online (Sandbox Code Playgroud)

然后,printAll()将打印if

  1. 列表中有MyClass的对象
  2. 列表中有Thread或ActionListener对象

你走在正确的轨道上.但我认为例如"如果MyClass列表中有对象则会打印"是有问题的.这听起来像是在定义运行时行为 - 泛型都是关于编译时间检查的.例如,即使它可能包含继承的实例,也无法传递a MyList<MySubclass>作为参数.我会改写它:MyList<? super MyClass>MyClass

printAll(MyList<? super MyClass>)只有在传递给一个调用时才会编译:

  1. MyList<MyClass>
  2. MyList<Thread>
  3. MyList<Runnable>
  4. MyList<ActionListener>
  5. MyList<EventListener>
  6. MyList<Object>
  7. MyList<? super X>其中XMyClass,Thread,Runnable,ActionListener,EventListener,或Object.

所以,在阅读了问题的许多答案后,我的理解是:

? extends T任何延伸T的类.因此,我们指的是T的子女.因此,T是上界.继承层次结构中最上层的类

? super Tsuper是指T的任何类/接口.因此,我们指的是T. T的所有父类,因此是下限.继承层次结构中最低级的类

关闭,但我不会说"孩子的T"或"父母的T",因为这些界限是包容性的 - 说" T或其子类型"和" T或其超类型" 会更准确.


Jac*_*ack 13

首先,T或者E或者K不是固定名称.它们只是类型变量,您可以决定它们的名称.T,E,K只是例子,但你可以把它Foo或什么的.

现在转到第一个问题:由于通配符?表示"任何未知"类型,未指定类型,因此在未指定类型上声明类通用没有任何意义.当您不关心类型时,在方法参数或变量中使用通配符很有用.

现在关于你的第二个问题:下限为你的泛型方法提供了更大的灵活性.两者extendssuper是相反:

  • ? extends T:一个未知类型,是一个子类型 T
  • ? super T:一种超级类型的未知类型 T

当你想要接受一个与T兼容的类型(因此T是一个那种类型)时,后者会很有用.这里可以找到一个实际的例子.