Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/304.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java <;之间的差异;?超级T>;以及<;?扩展T>;在爪哇_Java_Generics_Collections - Fatal编程技术网

Java <;之间的差异;?超级T>;以及<;?扩展T>;在爪哇

Java <;之间的差异;?超级T>;以及<;?扩展T>;在爪哇,java,generics,collections,Java,Generics,Collections,Listsuper是一个下限,extends是一个上限 根据: 解决方法是使用一种 我们尚未看到的有界通配符: 具有下限的通配符。这个 语法?super T表示一个未知数 是T(或T)的超类型的类型 自身;记住,超类型 关系是自反的)。它是双重的 有界通配符中的一个 使用,我们在哪里使用?延伸到 表示一个未知类型,该类型是 T亚型 扩展 使用的List的通配符声明扩展了只能从集合中获取的。你不能把它放进去。另外,虽然super同时允许get和put,但是get期间的返回类型是?super T通用

Listsuper是一个下限,extends是一个上限

根据:

解决方法是使用一种 我们尚未看到的有界通配符: 具有下限的通配符。这个 语法?super T表示一个未知数 是T(或T)的超类型的类型 自身;记住,超类型 关系是自反的)。它是双重的 有界通配符中的一个 使用,我们在哪里使用?延伸到 表示一个未知类型,该类型是 T亚型

扩展

使用
List的通配符声明扩展了只能从集合中获取的。你不能把它放进去。另外,虽然super同时允许get和put,但是get期间的返回类型是?super T

通用通配符针对两个主要需求:

从通用集合中读取 插入到泛型集合中 使用通用通配符定义集合(变量)有三种方法。这些是:

List<?>           listUknown = new ArrayList<A>();
List<? extends A> listUknown = new ArrayList<A>();
List<? super   A> listUknown = new ArrayList<A>();

List listUknown=new ArrayList

想象一下拥有这个层次结构

1.延伸 通过写作

    List<? extends C2> list;
    List<? super C2> list;
对于每种可能的情况,我们都有一组“可存储”类型:这里用图形表示7(红色)组

正如您所看到的,并不是每个案例都有一种常见的安全类型:

  • 不能
    list.add(new C2(){})list=new ArrayList()
  • 不能
    list.add(newd1(){})list=new ArrayList()
等等

2.超级的 通过写作

    List<? extends C2> list;
    List<? super C2> list;
对于每种可能的情况,我们都有一组“可存储”类型:这里用图形表示7(红色)组

如您所见,这里我们有七种常见的保险类型:
C2
D1
D2
E1
E2
E3
E4

  • 您可以
    list.add(newC2(){})因为,无论我们引用的是哪种列表,
    C2
    都是允许的
  • 您可以
    list.add(newd1(){})因为,无论我们引用的是哪种列表,
    D1
    都是允许的
等等。您可能注意到,这些类型对应于从type
C2
开始的层次结构

笔记 如果您希望进行一些测试,这里是完整的层次结构

interface A1{}
interface A2{}
interface A3{}
interface A4{}

interface B1 extends A1{}
interface B2 extends A1,A2{}
interface B3 extends A3,A4{}
interface B4 extends A4{}

interface C1 extends B2{}
interface C2 extends B2,B3{}
interface C3 extends B3{}

interface D1 extends C1,C2{}
interface D2 extends C2{}

interface E1 extends D1{}
interface E2 extends D1{}
interface E3 extends D2{}
interface E4 extends D2{}

我喜欢来自@Bert F的答案,但这是我的大脑所看到的

我手里拿着一个X。如果我想我的X写入一个列表,该列表需要是一个X列表,或者是一个我的X在写入时可以向上转换的事物列表,即X的任何超类

List<? super   X>
List基于我想解释一下我的理解

假设我们有三个班级作为

public class Fruit{}

public class Melon extends Fruit{}

public class WaterMelon extends Melon{}
我们有

List<? extends Fruit> fruitExtendedList = …

//Says that I can be a list of any object as long as this object extends Fruit.
让我们再试一次

Melon melon = fruitExtendedList.get(position)

//This is not valid because fruitExtendedList can be a list of Fruit only, it may not be 
//list of Melon or WaterMelon and in java we cannot assign sub class object to 
//super class object reference without explicitly casting it.
同样的情况也是如此

WaterMelon waterMelon = fruitExtendedList.get(position)
现在,让我们尝试在水果扩展列表中设置一些对象

Fruit fruit = fruitExtendedList.get(position)

//This is valid as it can only return Fruit or its subclass.
添加水果对象

fruitExtendedList.add(new Fruit())

//This in not valid because as we know fruitExtendedList can be a list of any 
//object as long as this object extends Fruit. So what if it was the list of  
//WaterMelon or Melon you cannot add Fruit to the list of WaterMelon or Melon.
添加瓜对象

fruitExtendedList.add(new Melon())

//This would be valid if fruitExtendedList was the list of Fruit but it may 
//not be, as it can also be the list of WaterMelon object. So, we see an invalid 
//condition already.
最后,让我们尝试添加西瓜对象

fruitExtendedList.add(new WaterMelon())

//Ok, we got it now we can finally write to fruitExtendedList as WaterMelon 
//can be added to the list of Fruit or Melon as any superclass reference can point 
//to its subclass object.
但是等一下如果有人决定做一种新型的柠檬怎么办呢

现在水果扩展列表可以是水果、甜瓜、西瓜或腌菜的列表

那么,我们的声明

fruitExtendedList.add(new WaterMelon())
也无效

基本上,我们可以说,我们不能将任何内容写入到一个扩展列表中。


这总结了
List这里最让人困惑的是,无论我们指定什么类型的限制,赋值都只能以一种方式工作:

baseClassInstance = derivedClassInstance;
您可能会认为
整数扩展了数字
,而
整数
在使用extends和super时将充当

通配符在方法参数中最有用。它们允许方法接口具有必要的灵活性

人们经常混淆何时使用extends和何时使用super-bounds。经验法则是“拿-放”原则。如果您从参数化容器中获取了一些内容,请使用extends

int totalFuel(List<? extends Vehicle> list) {
int total = 0;
for(Vehicle v : list) {
    total += v.getFuel();
}
return total;}

int totalFuel(List您可以浏览上面的所有答案,以了解为什么
.add()
仅限于
'
'将项目添加到列表中:

  • 列表<?扩展X>不允许在列表中添加任何内容,除了
    null

  • `List<? super Number> listvar;
    
  • 列表<?超级X>允许添加任何X(X或其子类型)或null

正在从列表中获取项目:

  • 当您从列表<?扩展X>中获取项目时,可以将其分配给X类型的变量或X的任何超类型,包括对象
  • 列表<?super X>中获取项目时,只能将其分配给
    对象
    类型的变量
一些例子:

    List<? extends Number> list1 = new ArrayList<Integer>();
    list1.add(null);  //OK
    Number n = list1.get(0);  //OK
    Serializable s = list1.get(0);  //OK
    Object o = list1.get(0);  //OK

    list1.add(2.3);  //ERROR
    list1.add(5);  //ERROR
    list1.add(new Object());  //ERROR
    Integer i = list1.get(0);  //ERROR

List投赞成票的答案涵盖了很多方面的细节。不过,我会尝试用不同的方式回答这个问题

有2件事我们需要考虑,

1.分配给列表变量
List示例,
遗传顺序假定为O>S>T>U>V

使用扩展关键字,

正确:

但为什么会出现错误呢? 让我们看看列表对象初始化的可能性

List<? extends T> Object = new List<T>();
List<? extends T> Object = new List<U>();
List<? extends T> Object = new List<V>();
但为什么在上述两种情况下会出现错误呢? 我们可以使用Object.add(new T());仅限于以下可能性

List<? super T> Object = new List<T>();
List<? super T> Object = new List<S>();
List<? super T> Object = new List<O>();

List我想将差异可视化。假设我们有:

class A { }
class B extends A { }
class C extends B { }

List@BertF,解释得很清楚,至少比Oracle博士的解释要好3405691582倍。我已经得出这个答案好几次了。我想我可以不止一次投票。你知道你是第一名吗?@Bert F'我在学习泛型之前喜欢java。@Danon更像那篇文章是这个答案的副本。这个answ呃是从2010年开始的,那个博客是从
Object myObject = melonSuperList.get(position)

//This is valid because Object cannot have any super class and above statement 
//can return only Fruit, Melon, WaterMelon or Object they all can be referenced by
//Object type reference.
melonSuperList.add(new Object())

//This is not valid as melonSuperList can be a list of Fruit or Melon.
//Note that Melon itself can be considered as super class of Melon.
melonSuperList.add(new Fruit())

//This is also not valid as melonSuperList can be list of Melon
melonSuperList.add(new Melon())

//This is valid because melonSuperList can be list of Object, Fruit or Melon and in 
//this entire list we can add Melon type object.
melonSuperList.add(new WaterMelon())

//This is also valid because of same reason as adding Melon
baseClassInstance = derivedClassInstance;
class Holder<T> {
    T v;
    T get() { return v; }
    void set(T n) { v=n; }
}
class A {
    public static void main(String[]args) {
        Holder<? extends Number> he = new Holder();
        Holder<? super Number> hs = new Holder();

        Integer i;
        Number n;
        Object o;

        // Producer Super: always gives an error except
        //       when consumer expects just Object
        i = hs.get(); // <? super Number> cannot be converted to Integer
        n = hs.get(); // <? super Number> cannot be converted to Number
                      // <? super Number> cannot be converted to ... (but
                      //       there is no class between Number and Object)
        o = hs.get();

        // Consumer Super
        hs.set(i);
        hs.set(n);
        hs.set(o); // Object cannot be converted to <? super Number>

        // Producer Extends
        i = he.get(); // <? extends Number> cannot be converted to Integer
        n = he.get();
        o = he.get();

        // Consumer Extends: always gives an error
        he.set(i); // Integer cannot be converted to <? extends Number>
        he.set(n); // Number cannot be converted to <? extends Number>
        he.set(o); // Object cannot be converted to <? extends Number>
    }
}
int totalFuel(List<? extends Vehicle> list) {
int total = 0;
for(Vehicle v : list) {
    total += v.getFuel();
}
return total;}
int totalValue(Valuer<? super Vehicle> valuer) {
int total = 0;
for(Vehicle v : vehicles) {
    total += valuer.evaluate(v);
}
return total;}
    List<? extends Number> list1 = new ArrayList<Integer>();
    list1.add(null);  //OK
    Number n = list1.get(0);  //OK
    Serializable s = list1.get(0);  //OK
    Object o = list1.get(0);  //OK

    list1.add(2.3);  //ERROR
    list1.add(5);  //ERROR
    list1.add(new Object());  //ERROR
    Integer i = list1.get(0);  //ERROR
    List<? super Number> list2 = new ArrayList<Number>();
    list2.add(null);  //OK
    list2.add(2.3);  //OK
    list2.add(5);  //OK
    Object o = list2.get(0);  //OK

    list2.add(new Object());  //ERROR
    Number n = list2.get(0);  //ERROR
    Serializable s = list2.get(0);  //ERROR
    Integer i = list2.get(0);  //ERROR
`List<? extends X> listvar;`
`List<? super Number> listvar;
List<? extends T> Object = new List<T>();
List<? extends T> Object = new List<U>();
List<? extends T> Object = new List<V>();
List<? extends T> Object = new List<S>();
List<? extends T> Object = new List<O>();
List<? super T> Object = new List<T>();
List<? super T> Object = new List<S>();
List<? super T> Object = new List<O>();
List<? super T> Object = new List<U>();
List<? super T> Object = new List<V>();
Object.add(new T()); //error
List<? extends T> Object = new List<T>();
List<? extends T> Object = new List<U>();
List<? extends T> Object = new List<V>();
List<? extends T> Object = new List<T>(); 
Object.add(new T()); // compiles fine without error
Object.add(new U()); // compiles fine without error
Object.add(new V()); // compiles fine without error

Object.add(new S()); //  error
Object.add(new O()); //  error
List<? super T> Object = new List<T>();
List<? super T> Object = new List<S>();
List<? super T> Object = new List<O>();
class A { }
class B extends A { }
class C extends B { }
|-------------------------|-------------------|---------------------------------|
|         wildcard        |        get        |              assign             |
|-------------------------|-------------------|---------------------------------|
|    List<? extends C>    |    A    B    C    |                       List<C>   |
|-------------------------|-------------------|---------------------------------|
|    List<? extends B>    |    A    B         |             List<B>   List<C>   |
|-------------------------|-------------------|---------------------------------|
|    List<? extends A>    |    A              |   List<A>   List<B>   List<C>   |
|-------------------------|-------------------|---------------------------------|
|-------------------------|-------------------|-------------------------------------------|
|         wildcard        |        add        |                   assign                  |
|-------------------------|-------------------|-------------------------------------------|
|     List<? super C>     |              C    |  List<Object>  List<A>  List<B>  List<C>  |
|-------------------------|-------------------|-------------------------------------------|
|     List<? super B>     |         B    C    |  List<Object>  List<A>  List<B>           |
|-------------------------|-------------------|-------------------------------------------|
|     List<? super A>     |    A    B    C    |  List<Object>  List<A>                    |
|-------------------------|-------------------|-------------------------------------------|