欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java 10 局部變量類(lèi)型推斷淺析

 更新時(shí)間:2019年06月13日 09:51:42   作者:邊城, dreamanzhao, 溪邊九節(jié), imqipan  
這篇文章主要介紹了Java 10 局部變量類(lèi)型推斷淺析,Java 10 引進(jìn)一種新的閃閃發(fā)光的特性叫做局部變量類(lèi)型推斷。文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下

前言

java 10 引進(jìn)一種新的閃閃發(fā)光的特性叫做局部變量類(lèi)型推斷。聽(tīng)起來(lái)很高大上吧?它是什么呢? 下面的兩個(gè)情景是我們作為 Java 開(kāi)發(fā)者認(rèn)為 Java 比較難使用的地方。

上下文:陳詞濫調(diào)和代碼可讀性

也許日復(fù)一日,你希望不再需要重復(fù)做一些事情。例如在下面的代碼(使用 Java 9 的集合工廠(chǎng)),左邊的類(lèi)型也許會(huì)感覺(jué)到冗余和平淡。

import static java.util.Map.entry;
List<String> cities = List.of("Brussels", "Cardiff", "Cambridge")
Map<String, Integer> citiesPopulation
= Map.ofEntries(entry("Brussels", 1_139_000),
entry("Cardiff", 341_000));

這是一個(gè)非常簡(jiǎn)單的例子,不過(guò)它也印證了傳統(tǒng)的 Java 哲學(xué):你需要為所有包含的簡(jiǎn)單表達(dá)式定義靜態(tài)類(lèi)型。再讓我們來(lái)看看有一些復(fù)雜的例子。舉例來(lái)說(shuō),下面的代碼建立了一個(gè)從字符串到詞的柱狀圖。它使用 groupingBy 收集器將流聚合進(jìn) Map 。groupingBy 收集器還可以以一個(gè)分類(lèi)函數(shù)為第一個(gè)參數(shù)建立映射的鍵和第二個(gè)收集器的 (counting()) 鍵計(jì)算關(guān)聯(lián)的數(shù)量。下面就是例子:

String sentence = "A simple Java example that explores what Java
10 has to offer";
Collector<String, ?, Map<String, Long>> byOccurrence
= groupingBy(Function.identity(), counting());
Map<String, Long> wordFrequency
= Arrays.stream(sentence.split(" "))
.collect(byOccurrence);

復(fù)雜表達(dá)式提取到一個(gè)變量或方法來(lái)提升代碼的可讀性和重用性,這是非常有意義的。在這里例子中,建立柱狀圖的邏輯使用了收集器。不幸地是,來(lái)自 groupingBy 的結(jié)果類(lèi)型幾乎是不可讀的!對(duì)于這一點(diǎn)你毫無(wú)辦法,你能做的只有觀察。

最重要的一點(diǎn)是當(dāng) Java 中增加新的類(lèi)庫(kù)的時(shí)候,他們開(kāi)發(fā)越來(lái)越多的泛型,這就為開(kāi)發(fā)者引進(jìn)了更多的公式化代碼(boilerplate code),從而帶來(lái)了額外的壓力。上面的例子并不是說(shuō)明了編寫(xiě)類(lèi)型就不好。很明顯,強(qiáng)制將為變量和方法簽名定義類(lèi)型的操作執(zhí)行為一種需要被尊重的協(xié)議,將有益于維護(hù)和理解。然而,為中間表達(dá)式聲明類(lèi)型也許會(huì)顯得無(wú)用和冗余。

類(lèi)型推斷的歷史

我們已經(jīng)在 Java 歷史上多次看到語(yǔ)言設(shè)計(jì)者添加“類(lèi)型推斷”來(lái)幫助我們編寫(xiě)更簡(jiǎn)潔的代碼。類(lèi)型推斷是一種思想:編譯器可以幫你推出靜態(tài)類(lèi)型,你不必自己指定它們。

最早從 Java 5 開(kāi)始就引入了泛型方法,而泛型方法的參數(shù)可以通過(guò)上下文推導(dǎo)出來(lái)。比如

這段代碼:

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

可以簡(jiǎn)化成:

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

然后,在 Java 7 中,可以在表達(dá)式中省略類(lèi)型參數(shù),只要這些參數(shù)能通過(guò)上下文確定。比如:

Map<String, List<String>> myMap = new HashMap<String,List<String>>();

可以使用尖括號(hào)<>運(yùn)算符簡(jiǎn)化成:

Map<User, List<String>> userChannels = new HashMap<>();

一般來(lái)說(shuō),編譯器可以根據(jù)周?chē)纳舷挛膩?lái)推斷類(lèi)型。在這個(gè)示例中,從左側(cè)可以推斷出 HashMap 包含字符串列表。

從 Java 8 開(kāi)始,像下面這樣的 Lambda 表達(dá)式

Predicate<String> nameValidation = (String x) -> x.length() > 0;

可以省略類(lèi)型,寫(xiě)成

Predicate<String> nameValidation = x -> x.length() > 0;

局部變量類(lèi)型推斷

隨著類(lèi)型越來(lái)越多,泛型參數(shù)有可能是另一個(gè)泛型,這種情況下類(lèi)型推導(dǎo)可以增強(qiáng)可讀性。Scala 和 C# 語(yǔ)言允許將局部變量的類(lèi)型聲明為 var,由編譯器根據(jù)初始化語(yǔ)句來(lái)填補(bǔ)合適的類(lèi)型。比如,前面對(duì) userChannels 的聲明可以寫(xiě)成這樣:

var userChannels = new HashMap<User, List<String>>();

也可以是根據(jù)方法的返回值(這里返回列表)來(lái)推斷:

var channels = lookupUserChannels("Tom");
channels.forEach(System.out::println);

這種思想稱(chēng)為局部變量類(lèi)型推斷,它已經(jīng)在 Java 10 中引入!

例如下面的代碼:

Path path = Paths.get("src/web.log");
try (Stream<String> lines = Files.lines(path)){
long warningCount
= lines
.filter(line -> line.contains("WARNING"))
.count();
System.out.println("Found " + warningCount + " warnings in the
log file");
} catch (IOException e) {
e.printStackTrace();
}

在 Java 10 中可以重構(gòu)成這樣:

var path = Paths.get("src/web.log");
try (var lines = Files.lines(path)){
var warningCount
= lines
.filter(line -> line.contains("WARNING"))
.count();
System.out.println("Found " + warningCount + " warnings in the
log file");
} catch (IOException e) {
e.printStackTrace();
}

上述代碼中的每個(gè)表達(dá)式仍然是靜態(tài)類(lèi)型(即值的類(lèi)型):

  • 局部變量 path 的類(lèi)型是 Path
  • 變量 lines 的類(lèi)型是 Stream<String>
  • 變量 warningCount 的類(lèi)型是 long

也就是說(shuō),如果給這些變量賦予不同值則會(huì)失敗。比如,像下面這樣的二次賦值會(huì)造成編譯錯(cuò)誤:

var warningCount = 5;
warningCount = "6";
| Error:
| incompatible types: java.lang.String cannot be converted to int
| warningCount = "6"

然而還有一些關(guān)于類(lèi)型推斷的小問(wèn)題;如果類(lèi) Car 和 Bike 都是 Vehicle 的子類(lèi),然后聲明

var v = new Car();

這里聲明的 v 的類(lèi)型是 Car 還是 Vehicle?這種情況下很好解釋?zhuān)驗(yàn)槌跏蓟鳎ㄟ@里是 Car)的類(lèi)型非常明確。如果沒(méi)有初始化器,就不能使用 var。稍后像這樣賦值

v = new Bike();

會(huì)出錯(cuò)。換句話(huà)說(shuō),var 并不能完美地應(yīng)用于多態(tài)代碼。

那應(yīng)該在哪里使用局部變量類(lèi)型推斷呢?

什么情況下局部類(lèi)型推斷會(huì)失效?你不能在字段和方法簽名中使用它。它只能用于局部變量,比如下面的代碼是不正確的:

public long process(var list) { }

不能在不明確初始化變量的情況下使用 var 聲明局部變量。也就是說(shuō),不能使用 var 語(yǔ)法聲明一個(gè)沒(méi)有賦值的變量。下面這段代碼

var x;

這會(huì)產(chǎn)生編譯錯(cuò)誤:

| Error:
| cannot infer type for local variable x
| (cannot use 'var' on variable without initializer)
| var x;
| ^----^

也不能把 var 聲明的變量初始化為 null。實(shí)事上,在后期初始化之前它究竟是什么類(lèi)型,這并不清楚。

| Error:
| cannot infer type for local variable x
| (variable initializer is 'null')
| var x = null;
| ^-----------^

不能在 Lambda 表達(dá)式中使用 var,因?yàn)樗枰鞔_的目標(biāo)類(lèi)型。下面的賦值就是錯(cuò)的:

var x = () -> {}
| Error:
| cannot infer type for local variable x
| (lambda expression needs an explicit target-type)
| var x = () -> {};
| ^---------------^

但是,下面的賦值卻是有效的,原因是等式右邊確實(shí)有一個(gè)明確的初始化。

var list = new ArrayList<>();

這個(gè)列表的靜態(tài)類(lèi)型是什么?變量的類(lèi)型被推導(dǎo)為 ArrayList<Object>,這完全失去了泛型的意義,所以你可能會(huì)想避免這種情況。

對(duì)無(wú)法表示的類(lèi)型(Non-Denotable Types)進(jìn)行推斷

Java 中存在大量無(wú)法表示的類(lèi)型——這些類(lèi)型存在于程序中,但是卻不能準(zhǔn)確地寫(xiě)出其名稱(chēng)。比如匿名類(lèi)就是典型的無(wú)法表示的類(lèi)型,你可以在匿名類(lèi)中添加字段和方法,但你沒(méi)辦法在 Java 代碼中寫(xiě)出匿名類(lèi)的名稱(chēng)。尖括號(hào)運(yùn)算符不能用于匿名類(lèi),而var 受到的限制會(huì)稍微少一些,它可以支持一些無(wú)法表示的類(lèi)型,詳細(xì)點(diǎn)說(shuō)就是匿名類(lèi)和交叉類(lèi)型。

var 關(guān)鍵字也能讓我們更有效地使用匿名類(lèi),它可以引用那些不可描述的類(lèi)型。一般來(lái)說(shuō)是可以在匿名類(lèi)中添加字段的,但是你不能在別的地方引用這些字段,因?yàn)樗枰兞吭谫x值時(shí)指定類(lèi)型的名稱(chēng)。比如下面這段代碼就不能通過(guò)編譯,因?yàn)?productInfo 的類(lèi)型是 Object,你不能通過(guò) Object 類(lèi)型來(lái)訪(fǎng)問(wèn) name 和 total 字段。

Object productInfo = new Object() {
String name = "Apple";
int total = 30;
};
System.out.println("name = " + productInfo.name + ", total = " +
productInfo.total);

使用 var 可以打破這個(gè)限制。把一個(gè)匿名類(lèi)對(duì)象賦值給以 var 聲明的局部變量時(shí),它會(huì)推斷出匿名類(lèi)的類(lèi)型,而不是把它當(dāng)作其父類(lèi)類(lèi)型。因此,匿名類(lèi)上聲明的字段就可以引用到。

var productInfo = new Object() {
String name = "Apple";
int total = 30;
};
System.out.println("name = " + productInfo.name + ", total = " +
productInfo.total);

乍一看這只是語(yǔ)言中比較有趣的東西,并不會(huì)有太大用處。但在某些情況下它確實(shí)有用。比如你想返回一些值作為中間結(jié)果的時(shí)候。一般來(lái)說(shuō),你會(huì)為此創(chuàng)建并維護(hù)一個(gè)新的類(lèi),但只會(huì)在一個(gè)方法中使用它。在 Collectors.averagingDouble() 的實(shí)現(xiàn)中就因?yàn)檫@個(gè)原因,使用了一個(gè) double 類(lèi)型的小數(shù)組。

有了 var 之后我們就有了更好的處理辦法 - 用匿名類(lèi)來(lái)保存中間值?,F(xiàn)在來(lái)思考一個(gè)例子,有一些產(chǎn)品,每個(gè)都有名稱(chēng)、庫(kù)存和貨幣價(jià)值或價(jià)值。我們要計(jì)算計(jì)算每一項(xiàng)的總價(jià)(數(shù)量*價(jià)值)。這些是我們要將每個(gè) Product 映射到其總價(jià)所需要的信息,但是為了讓信息更有意義,還需要加入產(chǎn)品的名稱(chēng)。下面的示例描述了在 Java 10 中如何使用 var 來(lái)實(shí)現(xiàn)這一功能:

var products = List.of(
new Product(10, 3, "Apple"),
new Product(5, 2, "Banana"),
new Product(17, 5, "Pear"));
var productInfos = products
.stream()
.map(product -> new Object() {
String name = product.getName();
int total = product.getStock() * product.getValue();
})
.collect(toList());
productInfos.forEach(prod ->
System.out.println("name = " + prod.name + ", total = " +
prod.total));
This outputs:
name = Apple, total = 30
name = Banana, total = 10
name = Pear, total = 85

并非所有無(wú)法表示的類(lèi)型都可以用 var - 它只支持匿名類(lèi)和交叉類(lèi)型。由通配符匹配的類(lèi)型就不能被推斷,這會(huì)避免與通配符相關(guān)的錯(cuò)誤被報(bào)告給 Java 程序員。支持無(wú)法表示的類(lèi)型的目的是在推斷類(lèi)型中盡量保留更多信息,讓人們可以利用局部變量并更好地重構(gòu)代碼。這一特性的初衷并不是要人們像上面的示例中那樣編寫(xiě)代碼,而是為了使用 var 簡(jiǎn)化處理無(wú)法表示類(lèi)型相關(guān)的一些問(wèn)題。以后是否會(huì)使用 var 來(lái)處理無(wú)法表示的類(lèi)型的一些細(xì)節(jié)問(wèn)題,尚不可知。

類(lèi)型推斷建議

類(lèi)型推斷確實(shí)有助于快速編寫(xiě) Java 代碼,但是可讀性如何呢?開(kāi)發(fā)者大約會(huì)花 10 倍于寫(xiě)代碼的時(shí)候來(lái)閱讀代碼,因此應(yīng)該讓代碼更易讀而不是更易寫(xiě)。var 對(duì)此帶來(lái)的改善程度總是主觀評(píng)價(jià)的,不可避免地會(huì)有人喜歡它,也會(huì)有人討厭它。你應(yīng)該關(guān)注的是如何幫助團(tuán)隊(duì)成員閱讀你的代碼,所以如果他們喜歡閱讀使用 var 的代碼,那就用,不然就不用。

有時(shí)候,顯示類(lèi)型也會(huì)降低可讀性。比如,在循環(huán)遍歷 Map 的 entryset 時(shí),你需要找到 Map.Entry 對(duì)象的類(lèi)型參數(shù)。這里有一個(gè)遍歷 Map 的示例,這個(gè) Map 將國(guó)家名稱(chēng)映射到其中的城市名稱(chēng)列表。

Map<String, List<String>> countryToCity = new HashMap<>();
// ...
for (Map.Entry<String, List<String>> citiesInCountry : countryToCity.entrySet()) {
List<String> cities = citiesInCountry.getValue();
// ...
}

然后用 var 來(lái)重寫(xiě)這段代碼,減少重復(fù)和繁瑣的東西:

var countryToCity = new HashMap<String, List<String>>();
// ...
for (var citiesInCountry : countryToCity.entrySet()) {
var cities = citiesInCountry.getValue();
// ...
}

這里不僅帶來(lái)了可讀性方面的優(yōu)勢(shì),在改進(jìn)和維護(hù)代碼方面也帶來(lái)了優(yōu)勢(shì)。如果我們?cè)陲@式類(lèi)型的代碼中將城市從 String 表示的名稱(chēng)改為 City 類(lèi),以保留更多城市信息,那就需要重寫(xiě)所有依賴(lài)于特定類(lèi)型的代碼,比如:

Map<String, List<City>> countryToCity = new HashMap<>();
// ...
for (Map.Entry<String, List<City>> citiesInCountry : countryToCity.entrySet()) {
List<City> cities = citiesInCountry.getValue();
// ...
}

但使用了 var 關(guān)鍵字和類(lèi)型推導(dǎo),我們就只需要修改第一行代碼就好:

var countryToCity = new HashMap<String, List<City>>();
// ...
for (var citiesInCountry : countryToCity.entrySet()) {
var cities = citiesInCountry.getValue();
// ...
}

這說(shuō)明了一個(gè)使用 var 變量的重要原則:不要為了易于編碼而優(yōu)化,也不要為了易讀而優(yōu)化,而要了易維護(hù)性而優(yōu)化。同時(shí)要考慮部分代碼可能以后會(huì)修改而要折衷考慮代碼的可讀性。當(dāng)然如果說(shuō)添加類(lèi)型推斷對(duì)代碼只會(huì)有好處略顯武斷,有時(shí)明確的類(lèi)型有助于代碼可讀性。特別是當(dāng)某些生成的表達(dá)式類(lèi)型不是很直觀時(shí),我將選擇顯式而不是隱式類(lèi)型,比如從下邊的代碼中我并不能看出 getCitiest() 方法會(huì)返回什么對(duì)象:

Map<String, List<City>> countryToCity = getCities();
var countryToCity = getCities();

既然要同時(shí)考慮到可讀性和 var ,那么如何折衷就成了一個(gè)新問(wèn)題,一個(gè)建議是:關(guān)注變量名,這很重要!因?yàn)?var 失去代碼的易讀性,看到這樣的代碼你根本不知道代碼的意圖是什么,這就使得起好一個(gè)變量名更加重要。理論上這是JAVA程序員應(yīng)努力的方面之一,實(shí)際上許多 Java 代碼可讀性的問(wèn)題根本不在語(yǔ)言的特性本身,而存在于一些變量的命名不太恰當(dāng)上。

IDE 中的類(lèi)型推斷

許多 IDE 都有提取局部變量的功能,它們可以正確地推斷出變量的類(lèi)型,并為你寫(xiě)出來(lái)。這一特性與 Java 10 的 var 有一些重復(fù)。IDE 的這個(gè)特性和 var 一樣都可以消除顯式書(shū)寫(xiě)類(lèi)型的必要性,但是它們?cè)谄渌矫嬗幸恍┎煌?/p>

局部提取功能會(huì)在代碼中生成完整的、類(lèi)型明確的局部變量。而 var 則是消除了在代碼寫(xiě)顯式書(shū)寫(xiě)類(lèi)型的必要。所以雖然他們?cè)诤?jiǎn)化書(shū)寫(xiě)代碼方面有著類(lèi)似的作用,但 var 對(duì)代碼可讀性的影響是局部提取功能所不具備的。就像我們前面提到,它多數(shù)時(shí)候會(huì)提高可讀性,但有時(shí)候會(huì)可能會(huì)降低可讀性。

與其它編程語(yǔ)言比較

Java 并不是首先實(shí)現(xiàn)變量類(lèi)型推斷的語(yǔ)言。類(lèi)型推斷在近幾十年來(lái)被廣泛應(yīng)用于其它語(yǔ)言中。實(shí)際上,Java 10 中通過(guò) var 帶來(lái)的類(lèi)型推斷非常有限,形式上也相對(duì)拘束。這是一種簡(jiǎn)單的實(shí)現(xiàn),可以將與 var 聲明相關(guān)的編譯錯(cuò)誤限制在一條語(yǔ)句當(dāng)中,因?yàn)?var 推斷算法只需要計(jì)算賦值給變量的表達(dá)式的類(lèi)型。此外,用在大多數(shù)語(yǔ)言中的 Hindley-Milner 類(lèi)型推斷算法在最壞的情況下會(huì)花費(fèi)指數(shù)級(jí)時(shí)間,這會(huì)降低 javac 的速度。

總結(jié)

var 對(duì)于 Java 語(yǔ)言的生產(chǎn)力和可讀性來(lái)說(shuō)是一項(xiàng)很不錯(cuò)的新特性,但不應(yīng)該止步于此。將來(lái)版本的 Java 將會(huì)繼續(xù)保持語(yǔ)言的革新和現(xiàn)代性。舉例來(lái)說(shuō),在 Java 10 發(fā)布僅僅 6 個(gè)月之后,就將發(fā)布并長(zhǎng)期支持的 Java 11,其 var 關(guān)鍵字將可以在 lambda 表達(dá)式的參數(shù)中使用。這能讓你擁有正式的參數(shù)類(lèi)型推斷能力,這很有用,不過(guò),你還是需要加上 Java 注解,下面是例子:

(@Nonnull var x, var y) -> x.process(y)

一些函數(shù)式編程的想法已經(jīng)被實(shí)現(xiàn),并且已經(jīng)為與將來(lái)的 Java 版本的結(jié)合做好準(zhǔn)備。舉例來(lái)說(shuō),模式匹配和值類(lèi)型。這并不意味著 Java 會(huì)變得不再是我們熟悉和喜愛(ài)的 Java,它只是會(huì)變得比以前更靈活、可讀性更強(qiáng),并且更簡(jiǎn)潔。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • java怎么連接并訪(fǎng)問(wèn)activemq

    java怎么連接并訪(fǎng)問(wèn)activemq

    這篇文章主要介紹了java怎么連接并訪(fǎng)問(wèn)activemq,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-07-07
  • Java Hibernate中的多種查詢(xún)方式及示例

    Java Hibernate中的多種查詢(xún)方式及示例

    Hibernate提供了多種查詢(xún)方式,包括HQL查詢(xún)、SQL查詢(xún)、QBC查詢(xún)和Criteria查詢(xún)等。HQL查詢(xún)是基于面向?qū)ο蟮牟樵?xún)語(yǔ)言,可以方便地進(jìn)行對(duì)象導(dǎo)航和多表查詢(xún);SQL查詢(xún)?cè)试S用戶(hù)直接使用SQL語(yǔ)句進(jìn)行查詢(xún);QBC查詢(xún)是基于Criteria的查詢(xún),具有類(lèi)型安全和可重用性的優(yōu)勢(shì)
    2023-04-04
  • jmeter正則表達(dá)式實(shí)例詳解

    jmeter正則表達(dá)式實(shí)例詳解

    正則表達(dá)式就是記錄文本規(guī)則的代碼。學(xué)習(xí)正則表達(dá)式最好就是從實(shí)例下手。下面我們通過(guò)實(shí)例代碼給大家介紹jmeter正則表達(dá)式的相關(guān)知識(shí),感興趣的朋友一起看看吧
    2021-12-12
  • Java效率提升神器之Guava-Joiner

    Java效率提升神器之Guava-Joiner

    這篇文章主要介紹了Java效率提升神器之Guava-Joiner,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-07-07
  • java?中如何實(shí)現(xiàn)?List?集合去重

    java?中如何實(shí)現(xiàn)?List?集合去重

    這篇文章主要介紹了java?中如何實(shí)現(xiàn)?List?集合去重,List?去重指的是將?List?中的重復(fù)元素刪除掉的過(guò)程,下文操作操作過(guò)程介紹需要的小伙伴可以參考一下
    2022-05-05
  • Java?項(xiàng)目中使用遞歸的小結(jié)

    Java?項(xiàng)目中使用遞歸的小結(jié)

    在 Java 中,遞歸是指在方法的定義中調(diào)用自身的過(guò)程,遞歸是基于方法調(diào)用棧的原理實(shí)現(xiàn)的:當(dāng)一個(gè)方法被調(diào)用時(shí),會(huì)在調(diào)用棧中創(chuàng)建一個(gè)對(duì)應(yīng)的棧幀,包含方法的參數(shù)、局部變量和返回地址等信息,這篇文章主要介紹了Java?項(xiàng)目中對(duì)使用遞歸的理解分享,需要的朋友可以參考下
    2024-07-07
  • Java annotation元注解原理實(shí)例解析

    Java annotation元注解原理實(shí)例解析

    這篇文章主要介紹了Java annotation元注解原理實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • SpringAOP+RabbitMQ+WebSocket實(shí)戰(zhàn)詳解

    SpringAOP+RabbitMQ+WebSocket實(shí)戰(zhàn)詳解

    這篇文章主要介紹了SpringAOP+RabbitMQ+WebSocket實(shí)戰(zhàn)詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-11-11
  • 淺析Java和Scala中的Future

    淺析Java和Scala中的Future

    這篇文章主要介紹了Java和Scala中的Future的相關(guān)資料,需要的朋友可以參考下
    2017-10-10
  • 那些年用httpclient時(shí)踩過(guò)的一些坑

    那些年用httpclient時(shí)踩過(guò)的一些坑

    這篇文章主要給大家介紹了關(guān)于那些年用httpclient時(shí)踩過(guò)的一些坑,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用httpclient具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05

最新評(píng)論