在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/Java/ java中 Arrays.asList返回的泛型類型如何確定?

java中 Arrays.asList返回的泛型類型如何確定?

最近在看java編程思想(第四版)的持有容器,書上11章223頁代碼如下

clipboard.png
在寫這個示例的時候,我發(fā)現(xiàn)紅框內(nèi)的代碼可以通過編譯,和書上不一致?

package com.xunli.holding;

import java.util.*;

class Snow {}

class Powder extends Snow {}
class Light extends  Powder {}
class Heavy extends Powder {}
class Crusty extends Snow {}
class Slush extends  Snow {}

public class AppleAndOrangeWithnotGenerics {

    public static void main(String[] args) {

       List<Snow> snow1 = Arrays.asList(
               new Crusty(), new Slush(), new Powder()
       );

        List<Snow> snow2 = Arrays.asList(
                new Light(), new Heavy()
        );

        List<Snow> snow3 = new ArrayList<Snow>();
        Collections.addAll(snow3, new Light(), new Heavy());

        List<Snow> snow4 = Arrays.<Snow>asList(new Light(), new Heavy());
    }
}

clipboard.png

這是為什么?

回答
編輯回答
毀了心

書比較老,Java8以下版本都不能編譯,Java8可以,你估計用的是Java8或更高版本。

2017年7月11日 12:06
編輯回答
爆扎

從 Java7 開始,官方就著手增強 Java 對泛型類型的推導(dǎo)能力,對應(yīng)的項目有 JDK7 的 JSR 334 (Project Coin) 和 JDK8 的 JEP 101: Generalized Target-Type Inference。

我看樓上有回答說 Java8 以下版本不可以編譯你的代碼,這是不對的。使用 Java7 也可以正確編譯你的代碼,因為 JDK7 對于泛型類型的推導(dǎo)不僅僅只有 “菱形推導(dǎo)”,還添加了部分目標(biāo)類型推導(dǎo)的功能,可以參考 Oracle 的官方文檔 Type Inference,看到 Target Types 這一節(jié),我摘取部分:

The Java compiler takes advantage of target typing to infer the type parameters of a generic method invocation. The target type of an expression is the data type that the Java compiler expects depending on where the expression appears. Consider the method Collections.emptyList, which is declared as follows:

static <T> List<T> emptyList();

Consider the following assignment statement:

List<String> listOne = Collections.emptyList();

This statement is expecting an instance of List<String>; this data type is the target type. Because the method emptyList returns a value of type List<T>, the compiler infers that the type argument T must be the value String. This works in both Java SE 7 and 8.

可以看到,對于 JDK7 以及之后版本的 JDK 來說,它們至少都已經(jīng)擁有了根據(jù)返回值來確定泛型類型的能力。


再回到你的代碼,比如你寫:

List<Snow> snow1 = Arrays.asList(
    new Crusty(), new Slush(), new Powder()
);

編譯器可以根據(jù)你的返回值類型(List<Snow>)來推斷出你傳入的每一個參數(shù)都是一個 Snow,從而判斷參數(shù)是否正確(即判斷每一個參數(shù)的類型是否都是 Snow 或者其子類)。對于下面的代碼效果一樣:

List<Snow> powders = Arrays.asList(
    new Light(), new Heavy()
);

因為 LightHeavy 都是 Snow 的間接子類。


如果你不寫上返回值,而是直接寫上代碼:

Arrays.asList(
    new Light(), new Heavy()
);

然后用 IntelliJ IDEA 的自動生成返回的變量的功能(我認(rèn)為 IDE 也是調(diào)用的編譯器提供的相關(guān) API 的功能,或者至少是符合編譯器要求的功能):
Introduce local variable

你會發(fā)現(xiàn)生成的是 List<Powder>
Result of introducing local variable

這種時候,沒有返回值,那么編譯器會嘗試去找到傳入的所有參數(shù)的最近的交集,即 Powder,所以編譯推導(dǎo)出此時的 T 的類型為 Powder


綜上,Java 的編譯器,從很早以前就真的開始變得越來越聰明了呢。

2017年2月22日 11:22
編輯回答
孤星

表示我用java8沒通過

clipboard.png

2018年4月14日 13:46