java泛型超级关键字

java generics super keyword

我讨论过这些话题

  • 仿制药……?超级T
  • 用"super"关键字绑定泛型
  • 小精灵

    不过,我似乎仍然对super关键字有点迷茫:

  • 当我们声明这样的集合时:

    1
    2
    3
    List<? super Number> list = null;
    list.add(new Integer(0));//this compiles
    list.add(new Object());//this doesn't compile

    不应该是相反的吗?我们有一个列表,其中包含一些(未知类型的)对象,这些对象是Number的父对象。因此,Object应该是合适的(因为它是Number的父母),而Integer不应该是合适的,相反的情况是有原因的。

  • 如果我们有以下代码

    1
    2
    3
    4
    5
    6
    7
    static void test(List<? super Number> param) {
        param.add(new Integer(2));
    }
    public static void main(String[] args) {
        ArrayList<String> sList = new ArrayList<String>();
        test(sList);            //will never compile, however...
    }

    编译上述代码是不可能的(我的理智表明这是正确的行为),但基本逻辑可以证明是相反的:

    埃多克斯1〔5〕

    我知道这很疯狂,但这不是他们不允许构造的原因吗?如果是,那么为什么允许使用

  • 有人能帮我恢复这个逻辑链缺失的部分吗?


    List中的有界通配符可以捕获Number及其任何超类型。由于Number extends Object implements Serializable,这意味着目前被List所捕获的可转换类型只有:

    • List
    • 埃多克斯1〔15〕
    • 埃多克斯1〔63〕
    • 小精灵

      请注意,您可以将cx1〔64〕扩展到上述任何类型。但是,不能将add(new Object())转换为ListList,因为这违反了通用类型安全规则。

      因此,您不能将add的任何超类型的Number转换为List,这并不是真的;这根本不是有界通配符和捕获转换的工作方式。你不会声明一个List,因为你可能想在它上面添加一个Object(你不能!);你这样做是因为你想添加Number对象(即它是Number的"消费者"),简单地说,List太限制了。

      工具书类

      • 安吉丽卡·兰格的仿制药常见问题解答
        • 什么是有界通配符?
        • 我什么时候使用下界的通配符参数化类型?("当具体的参数化类型限制过大时。")
        • 为什么类型参数没有下限?(因为它没有意义。)
        • 小精灵

        • JLS 5.1.10捕获转换
        • 小精灵另请参见

          • 有效Java第二版,项目28:使用有界通配符增加API灵活性
            • "PECS代表Producer-extends,Consumer-super"。
            • 小精灵

              小精灵相关问题

              • 太多无法列出,PEC、new Integer(0)valueOf
              • 小精灵


                对于第一部分,ListList匹配,但不能将Object添加到List中。这就是为什么你不能在List中添加Object的原因。

                另一方面,您可以将Number的每个子类(包括Number)添加到您的列表中。

                第二部分,StringObject,但String不是Number的超类。

                如果它是这样工作的,因为每个类都是Object的子类,那么super就没有意义了。

                让我们看看每一个可能的情况与List

                • 通过的名单是一个List
                  • List将起作用
                  • Object相吻合。
                  • 可以将Number的任何子类型添加到List中。
                  • 即使您也可以在其中添加String,您唯一能确定的是您可以添加Number的任何子类。
                  • 小精灵

                    小精灵

                    • 通过的列表是一个List
                      • List将起作用
                      • Number相匹配。
                      • 可以将Number的任何子类型添加到List中。
                      • 小精灵

                        小精灵

                        • 通过的名单是List(或Number的任何子类):
                          • List不起作用
                          • integer是Number的一个子类,所以我们要避免它
                          • 即使IntegerNumber相匹配,也不能简称为在List中添加Number的任何子类(例如Float)。
                          • super不是一个子类。
                          • 小精灵

                            小精灵

                            • 通过的列表是一个List(或不扩展Number的任何类,也不在Number的"超级层次"中(即NumberObject中):
                              • List不起作用
                              • String不符合Number的"超级层次"
                              • 即使String符合Object(这是Number的一个超类),您也不一定能够将Number添加到List中,该List包含Number的一个超类中的任何子类。
                              • super并不表示其中一个超类的任何子类,它只表示其中一个超类。
                              • 小精灵

                                小精灵

                                它是如何工作的?

                                你可以说,只要你能用你键入的List添加Number的任何子类,它就尊重super关键字。


                                我没有得到它的一段。许多的答案在这里,和其他专门问题的表演和在某些时候usages是错误的,但不太。。。。。。。。

                                最后是怎么得到它。如果有一个功能,adds Numbers两个List,他们可能想添加型MySuperEfficientNumber(这是我自己的自定义类,Numberimplements(但不是一个subclass冰系Integer)。现在来电者可能不知道任何关于MySuperEfficientNumberAs Long,但当他们知道治疗的元素添加到列表的特异性为没有更多的比Number,他们会被罚款。

                                我宣布我的方法为:

                                1
                                public static void addNumbersToList(List<? extends Number> numbers)

                                当时的《来电者可以在一个List通。如果我的方法添加一个MySuperEfficientNumber尽头的numbers的来电,然后会有一个List没有语言学院Integers和下面的代码不会工作

                                1
                                2
                                3
                                4
                                5
                                List<Integer> numbers = new ArrayList<Integer>();
                                addNumbersToList(numbers);

                                // The following would return a MySuperEfficientNumber not an Integer
                                Integer i = numbers.get(numbers.size()-1)

                                很明显,这是不能工作的。和误差会在《addNumbersToList方法。你会得到什么样的:

                                1
                                The method add... is not applicable for the arguments (MySuperEfficientNumber)

                                因为我可以是任何numbersNumber特异性检查,不necessarily冰的东西,MySuperEfficientNumber与兼容。如果在两个翻转的声明super使用的方法,将编译没有错误,但呼叫者的代码:将失败。

                                1
                                The method addNumbersToList(List<? super Number>)... is not applicable for the arguments (List<Integer>)

                                我的方法,因为冰说,"我不认为你能做什么List比大学更Number特异性。在所有的品种可能会增加两个奇怪的Numbers狡猾,你只是有两个问题用的。如果你想让他们想的东西甚至更为一般比Number-样Object-好的,好的,我会保证他们至少Numbers,但你不可以享受一般治疗它们,如果你想要的。"

                                extends尽头冰说,"我不真的关心你的脸颊,你给我的大学ListAA,AA大每个元件的至少一Number冰。它可以是任何一种Number怪异,甚至你自己的自定义方式,IP Numbers。As Long As,他们实施的接口,我们的好。我不会在任何两个增你的诡计,因为我不知道什么是混凝土的实际类型,你是有用的。"


                                List意味的引用类型的变量suggests我们有一个列表或serializables对象数。

                                的理由你不能添加一个对象,因为冰的编译器不知道这些类都定义在一般的实际instantiated对象,所以它只允许你两遍数或subtypes of number,双整数的类,所以在线。

                                让我们说,我们有一个方法,一List归来。the creation of the对象的方法封装在里面的冰从我们的观点,我们只是不能说,如果它是这样的:什么的

                                List returnValue = new LinkedList();

                                List returnValue = new ArrayList();

                                所以,我可以是通用类型的对象或数据。在两个案例,我们会允许两个数的增加,但只在一个案例,我们会允许两个附加对象。

                                你必须区分"之间的引用类型和对象的实际类型在这情况。


                                这样一ListList我们可以implicitely铸造每个NumberAncestorOfNumber其超类。

                                本:我认为通用型需求两个????在下面的实例?

                                1
                                2
                                3
                                4
                                5
                                6
                                7
                                8
                                9
                                10
                                11
                                12
                                InputStream mystream = ...;

                                void addTo(List<????> lsb) {
                                    lsb.add(new BufferedInputStream(mystream));
                                }

                                List<BufferedInputStream> lb = new ArrayList<>();
                                List<InputStream> li = new ArrayList<>();
                                List<Object> lo = new ArrayList<>();

                                ...
                                { addTo(lb); addTo(li); addTo(lo); }

                                答案:????冰的东西,我们可以BufferedInputStream铸造,这是非常相同的或由其祖先的一? super BufferedInputStream


                                可以提供一个非常简单的实例。

                                1
                                2
                                public void add(List<? super Number> list) {
                                }

                                这将允许这些保证金

                                1
                                add(new LinkedList<Number>());

                                鸭类数量超过一切

                                1
                                add(new LinkedList<Object>());

                                但无渣槽下面的层次

                                1
                                add(new LinkedList<Double>());

                                1
                                add(new LinkedList<Integer>());

                                所以既然它不是透明的程序知道不管你给一个号码或战略与对象的编译器不能允许你添加第二个以上的任何信息。

                                例如,一个表将不接受对象的对象spite大学会接受世界卫生组织的一个号码。但由于这只透明的冰槽将是有效的输入值和它的子类。