第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

用簡單的英語解釋協(xié)方差,不變性和相反性?

用簡單的英語解釋協(xié)方差,不變性和相反性?

猛跑小豬 2019-11-21 12:49:48
今天,我讀了一些有關Java中協(xié)方差,協(xié)方差(和不變性)的文章。我閱讀了英文和德文的Wikipedia文章,以及其他來自IBM的博客文章和文章。但是我對這些到底是什么還是有些困惑?有人說這與類型和子類型之間的關系有關,有人說與類型轉換有關,有人說它用于確定方法是被重寫還是被重載。因此,我正在尋找一種簡單易懂的英語解釋,它向初學者展示了協(xié)方差和逆方差(和不變性)。加號是一個簡單的例子。
查看完整描述

3 回答

?
犯罪嫌疑人X

TA貢獻2080條經驗 獲得超4個贊

有人說這與類型和子類型之間的關系有關,有人說與類型轉換有關,還有人說它用于確定方法是被覆蓋還是被重載。


上述所有的。


本質上,這些術語描述了類型轉換如何影響子類型關系。也就是說,如果A和B是類型,f則是類型轉換,并且≤子類型關系(即A ≤ B表示A是的子類型B),我們有


f是協(xié)變的,如果A ≤ B暗示f(A) ≤ f(B)

f是矛盾的,如果A ≤ B暗示f(B) ≤ f(A)

f 如果以上兩個都不成立,則是不變的

讓我們考慮一個例子。讓f(A) = List<A>哪里List聲明


class List<T> { ... } 

是f協(xié)變,逆變還是不變?協(xié)變意味著a List<String>是的子類型List<Object>,相反,a List<Object>是的子類型,List<String>并且不變都不是另一個的子類型,即List<String>和List<Object>是不可轉換的類型。在Java中,后者是正確的,我們說(某種程度上是非正式的)泛型是不變的。


另一個例子。讓f(A) = A[]。是f協(xié)變,逆變還是不變?也就是說,String []是Object []的子類型,Object []是String []的子類型,還是兩者都不是子類型?(答案:在Java中,數(shù)組是協(xié)變的)


這仍然很抽象。為了更加具體,讓我們看一下Java中的哪些操作是根據子類型關系定義的。最簡單的例子是分配。該聲明


x = y;

僅在時才編譯typeof(y) ≤ typeof(x)。也就是說,我們剛剛了解到


ArrayList<String> strings = new ArrayList<Object>();

ArrayList<Object> objects = new ArrayList<String>();

不會在Java中編譯,但是


Object[] objects = new String[1];

將。


子類型關系很重要的另一個示例是方法調用表達式:


result = method(a);

非正式地說,該語句是通過將a方法的值分配給方法的第一個參數(shù),然后執(zhí)行方法的主體,然后將方法的返回值分配給來評估的result。就像最后一個示例中的普通分配一樣,“右側”必須是“左側”的子類型,即,僅當typeof(a) ≤ typeof(parameter(method))和時,此語句才有效returntype(method) ≤ typeof(result)。也就是說,如果方法通過以下方式聲明:


Number[] method(ArrayList<Number> list) { ... }

以下任何表達式都不會編譯:


Integer[] result = method(new ArrayList<Integer>());

Number[] result = method(new ArrayList<Integer>());

Object[] result = method(new ArrayList<Object>());


Number[] result = method(new ArrayList<Number>());

Object[] result = method(new ArrayList<Number>());

將。


子類型很重要的另一個示例是重載??紤]:


Super sup = new Sub();

Number n = sup.method(1);

哪里


class Super {

    Number method(Number n) { ... }

}


class Sub extends Super {

    @Override 

    Number method(Number n);

}

非正式地,運行時會將其重寫為:


class Super {

    Number method(Number n) {

        if (this instanceof Sub) {

            return ((Sub) this).method(n);  // *

        } else {

            ... 

        }

    }

}

為了編譯標記行,覆蓋方法的方法參數(shù)必須是覆蓋方法的方法參數(shù)的超類型,返回類型必須是覆蓋方法的子類型。從形式上來講,f(A) = parametertype(method asdeclaredin(A))必須f(A) = returntype(method asdeclaredin(A))至少是協(xié)變的,如果必須至少是協(xié)變的。


請注意上面的“至少”。這些是任何合理的靜態(tài)類型安全的面向對象編程語言都將強制執(zhí)行的最低要求,但是編程語言可能會選擇更嚴格的標準。對于Java 1.4,在覆蓋方法(即parametertype(method asdeclaredin(A)) = parametertype(method asdeclaredin(B)),覆蓋)時,參數(shù)類型和方法返回類型必須相同(類型擦除除外)。從Java 1.5開始,重寫時允許使用協(xié)變返回類型,即以下內容將在Java 1.5中進行編譯,但在Java 1.4中不進行編譯:


class Collection {

    Iterator iterator() { ... }

}


class List extends Collection {

    @Override 

    ListIterator iterator() { ... }

}

我希望我覆蓋了所有內容,或者更確切地說,是劃傷了表面。我仍然希望它將有助于理解類型差異的抽象但重要的概念。


查看完整回答
反對 回復 2019-11-21
  • 3 回答
  • 0 關注
  • 537 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號