自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java簡(jiǎn)潔之道

移動(dòng)開發(fā)
計(jì)算機(jī)專家在問題求解時(shí)非常重視表達(dá)式簡(jiǎn)潔性的價(jià)值。Unix的先驅(qū)者Ken Thompson曾經(jīng)說(shuō)過非常著名的一句話:“丟棄1000行代碼的那一天是我最有成效的一天之一?!边@對(duì)于任何一個(gè)需要持續(xù)支持和維護(hù)的軟件項(xiàng)目來(lái)說(shuō),都是一個(gè)當(dāng)之無(wú)愧的目標(biāo)

[[143085]]

計(jì)算機(jī)專家在問題求解時(shí)非常重視表達(dá)式簡(jiǎn)潔性的價(jià)值。Unix的先驅(qū)者Ken Thompson曾經(jīng)說(shuō)過非常著名的一句話:“丟棄1000行代碼的那一天是我最有成效的一天之一。”這對(duì)于任何一個(gè)需要持續(xù)支持和維護(hù)的軟件項(xiàng)目來(lái)說(shuō),都是一個(gè)當(dāng)之無(wú)愧的目標(biāo)。早期的Lisp貢獻(xiàn)者Paul Graham甚至將語(yǔ)言的簡(jiǎn)潔性等同為語(yǔ)言的能力。這種對(duì)能力的認(rèn)識(shí)讓可以編寫緊湊、簡(jiǎn)介的代碼成為許多現(xiàn)代軟件項(xiàng)目選擇語(yǔ)言的首要標(biāo)準(zhǔn)。

任何程序都可以通過重構(gòu),去除多余的代碼或無(wú)用的占位符,如空格,變得更加簡(jiǎn)短,不過某些語(yǔ)言天生就善于表達(dá),也就特別適合于簡(jiǎn)短程序的編寫。認(rèn)識(shí)到這一點(diǎn)之后,Perl程序員普及了代碼高爾夫競(jìng)賽;其目標(biāo)是用盡可能短的代碼量解決某一特定的問題或者實(shí)現(xiàn)某個(gè)指定的算法。APL語(yǔ)言的設(shè)計(jì)理念是利用特殊的圖形符號(hào)讓程序員用很少量的代碼就可以編寫功能強(qiáng)大的程序。這類程序如果實(shí)現(xiàn)得當(dāng),可以很好地映射成標(biāo)準(zhǔn)的數(shù)學(xué)表達(dá)式。簡(jiǎn)潔的語(yǔ)言在快速創(chuàng)建小腳本時(shí)非常高效,特別是在目的不會(huì)被簡(jiǎn)潔所掩蓋的簡(jiǎn)潔明確的問題域中。

相比于其他程序設(shè)計(jì)語(yǔ)言,Java語(yǔ)言的冗長(zhǎng)已經(jīng)名聲在外。其主要原因是由于程序開發(fā)社區(qū)中所形成的慣例,在完成任務(wù)時(shí),很多情況下,要更大程度地考慮描述性和控制。例如,長(zhǎng)期來(lái)看,長(zhǎng)變量名會(huì)讓大型代碼庫(kù)的可讀性和可維護(hù)性更強(qiáng)。描述性的類名通常會(huì)映射為文件名,在向已有系統(tǒng)中增加新功能時(shí),會(huì)顯得很清晰。如果能夠一直堅(jiān)持下去,描述性名稱可以極大簡(jiǎn)化用于表明應(yīng)用中某一特定的功能的文本搜索。這些實(shí)踐讓Java在大型復(fù)雜代碼庫(kù)的大規(guī)模實(shí)現(xiàn)中取得了極大的成功。

對(duì)于小型項(xiàng)目來(lái)說(shuō),簡(jiǎn)潔性則更受青睞,某些語(yǔ)言非常適于短腳本編寫或者在命令提示符下的交互式探索編程。Java作為通用性語(yǔ)言,則更適用于編寫跨平臺(tái)的工具。在這種情況下,“冗長(zhǎng)Java”的使用并不一定能夠帶來(lái)額外的價(jià)值。雖然在變量命名等方面,代碼風(fēng)格可以改變,不過從歷史情況來(lái)看,在一些基本的層面上,與其他語(yǔ)言相比,完成同樣的任務(wù),Java語(yǔ)言仍需更多的字符。為了應(yīng)對(duì)這些限制,Java語(yǔ)言一直在不斷地更新,以包含一些通常稱為“語(yǔ)法糖”的功能。用這些習(xí)語(yǔ)可以實(shí)現(xiàn)更少的字符表示相同功能的目標(biāo)。與其對(duì)應(yīng)的更加冗長(zhǎng)的配對(duì)物相比,這些習(xí)語(yǔ)更受程序開發(fā)社區(qū)的歡迎,通常會(huì)被社區(qū)作為通用用法快速地采用。

本文將著重介紹編寫簡(jiǎn)潔Java代碼的***實(shí)踐,特別是關(guān)于JDK8中新增的功能。簡(jiǎn)而言之,Java 8中Lambda表達(dá)式的引入讓更加優(yōu)雅的代碼成為可能。這在用新的Java Streaming API處理集合時(shí)尤其明顯。

冗長(zhǎng)的Java

Java代碼冗長(zhǎng)之所以名聲在外,一部分原因是由于其面向?qū)ο蟮膶?shí)現(xiàn)風(fēng)格。在許多語(yǔ)言中,只需要一行包含不超過20個(gè)字符的代碼就可以實(shí)現(xiàn)經(jīng)典的“Hello World”程序示例。而在Java中,除了需要類定義中所包含的main方法之外,在main方法中還需要包含一個(gè)方法調(diào)用,通過System.out.println()將字符串打印到終端。即使在使用最少的方法限定詞、括號(hào)和分號(hào),并且將所有空格全都刪除的極限情況下,“Hello World”程序最少也需要86個(gè)字符。為了提高可讀性,再加上空格和縮進(jìn),毋庸置疑,Java版的“Hello World”程序給人的***印象就是冗長(zhǎng)。

Java代碼冗長(zhǎng)一部分原因還應(yīng)歸咎于Java社區(qū)將描述性而非簡(jiǎn)潔性作為其標(biāo)準(zhǔn)。就這一點(diǎn)而言,選擇與代碼格式美學(xué)相關(guān)的不同標(biāo)準(zhǔn)是無(wú)關(guān)緊要的。此外,樣板代碼的方法和區(qū)段可以包含在整合到API中的方法中。無(wú)需犧牲準(zhǔn)確性或清晰度,著眼于簡(jiǎn)潔性的程序代碼重構(gòu)可以大大簡(jiǎn)化冗余Java代碼。

有些情況下,Java代碼冗長(zhǎng)之所以名聲在外是由于大量的老舊代碼示例所帶來(lái)的錯(cuò)覺。許多關(guān)于Java的書籍寫于多年之前。由于在整個(gè)萬(wàn)維網(wǎng)最初興起時(shí),Java便已經(jīng)存在,許多Java的在線資源所提供的代碼片段都源自于Java語(yǔ)言最早的版本。隨著時(shí)間的推移,一些可見的問題和不足不斷得到完善,Java語(yǔ)言也日趨成熟,這也就導(dǎo)致即使十分準(zhǔn)確并實(shí)施的當(dāng)?shù)陌咐?,可能也未能有效利用后?lái)的語(yǔ)言習(xí)語(yǔ)和API。

Java的設(shè)計(jì)目標(biāo)包括面向?qū)ο?、易于上手(在?dāng)時(shí),這意味著使用C++格式的語(yǔ)法),健壯、安全、可移植、多線程以及高性能。簡(jiǎn)潔并非其中之一。相比于用面向?qū)ο笳Z(yǔ)法實(shí)現(xiàn)的任務(wù),函數(shù)式語(yǔ)言所提供的替代方案要簡(jiǎn)潔的多。Java 8中新增的Lambda表達(dá)式改變了Java的表現(xiàn)形式,減少了執(zhí)行許多通用任務(wù)所需的代碼數(shù)量,為Java開啟了函數(shù)式編程習(xí)語(yǔ)的大門。

函數(shù)式編程

函數(shù)式編程將函數(shù)作為程序開發(fā)人員的核心結(jié)構(gòu)。開發(fā)人員可以以一種非常靈活的方式使用函數(shù),例如將其作為參數(shù)傳遞。利用Lambda表達(dá)式的這種能力,Java可以將函數(shù)作為方法的參數(shù),或者將代碼作為數(shù)據(jù)。Lambda表達(dá)式可以看作是一個(gè)與任何特定的類都無(wú)關(guān)的匿名方法。這些理念有著非常豐富多彩并且引人入勝的數(shù)學(xué)基礎(chǔ)。

函數(shù)式編程和Lambda表達(dá)式仍然是比較抽象、深?yuàn)W的概念。對(duì)于開發(fā)人員來(lái)說(shuō),主要關(guān)注如何解決實(shí)際生產(chǎn)中的任務(wù),對(duì)于跟蹤***的計(jì)算趨勢(shì)可能并不感興趣。隨著Lambda表達(dá)式在Java中的引入,對(duì)于開發(fā)人員來(lái)說(shuō)對(duì)這些新特性的了解至少需要能夠達(dá)到可以讀懂其他開發(fā)人員所編寫代碼的程度。這些新特性還能帶來(lái)實(shí)際的好處——可以影響并發(fā)系統(tǒng)的設(shè)計(jì),使其擁有更優(yōu)的性能。而本文所關(guān)心的是如何利用這些機(jī)制編寫簡(jiǎn)潔而又清晰的代碼。

之所以能夠用Lambda表達(dá)式生成簡(jiǎn)潔的代碼,有如下幾個(gè)原因。局部變量的使用量減少,因此聲明和賦值的代碼也隨之減少。循環(huán)被方法調(diào)用所替代,從而將三行以上的代碼縮減為一行。本來(lái)在嵌套循環(huán)和條件語(yǔ)句中的代碼現(xiàn)在可以放置于一個(gè)單獨(dú)的方法中。實(shí)現(xiàn)連貫接口,可以將方法以類似于Unix管道的方式鏈接在一起。以函數(shù)式的風(fēng)格編寫代碼的凈效應(yīng)并不只限于可讀性。此類代碼可以避免狀態(tài)維護(hù)并且不會(huì)產(chǎn)生副作用。這種代碼還能夠產(chǎn)生易于并行化,提高處理效率的額外收益。

Lambda表達(dá)式

與Lambda表達(dá)式相關(guān)的語(yǔ)法比較簡(jiǎn)單直白,不過又有別于Java之前版本的習(xí)語(yǔ)。一個(gè)Lambda表達(dá)式由三部分組成,參數(shù)列表、箭頭和主體。參數(shù)列表可以包含也可以不包含括號(hào)。此外還新增了由雙冒號(hào)組成的相關(guān)操作符,可以進(jìn)一步縮減某些特定的Lambda表達(dá)式所需的代碼量。這又稱為方法引用

線程創(chuàng)建

在這個(gè)示例中,將會(huì)創(chuàng)建并運(yùn)行一個(gè)線程。Lambda表達(dá)式出現(xiàn)在賦值操作符的右側(cè),指定了一個(gè)空的參數(shù)列表,以及當(dāng)線程運(yùn)行時(shí)寫到標(biāo)準(zhǔn)輸出的簡(jiǎn)單的消息輸出。

  1. Runnable r1 = () -> System.out.print("Hi!"); 
  2. r1.run() 

參數(shù)列表

箭頭

主體

()

->

System.out.print("Hi!");

處理集合

Lambda表達(dá)式的出現(xiàn)會(huì)被開發(fā)人員注意到的首要位置之一就是與集合API相關(guān)。假設(shè)我們需要將一個(gè)字符串列表根據(jù)長(zhǎng)度排序。

  1. java.util.List<String> l; 
  2. l= java.util.Arrays.asList(new String[]{"aaa""b""cccc""DD"}); 

可以創(chuàng)建一個(gè)Lambda表達(dá)式實(shí)現(xiàn)此功能。

  1. java.util.Collections.sort(l, (s1, s2) -> 
  2.        new Integer(s1.length()). 
  3.            compareTo(s2.length()) 

這個(gè)示例中包含兩個(gè)傳遞給Lambda表達(dá)式體的參數(shù),以比較這兩個(gè)參數(shù)的長(zhǎng)度。

參數(shù)列表

箭頭

主體

(s1, s2)

->

new Integer(s1.length()).

compareTo(s2.length()));

除此之外還有許多替代方案,在無(wú)需使用標(biāo)準(zhǔn)的“for”或“while”循環(huán)的前提下,就可以操作列表中的各個(gè)元素。通過向集合的“forEach”方法傳入Lambda表達(dá)式也可以完成用于比較的語(yǔ)義。這種情況下,只有一個(gè)參數(shù)傳入,也就無(wú)需使用括號(hào)。

  1. forEach(e -> System.out.println(e)); 

Argument List

Arrow

Body

e

->

System.out.println(e)

這個(gè)特殊的示例還可以通過使用方法引用將包含類和靜態(tài)方法分開的方式進(jìn)一步減少代碼量。每個(gè)元素都會(huì)按順序傳入println方法。

  1. forEach(System.out::println) 

java.util.stream是在Java 8中新引入的包,以函數(shù)式程序開發(fā)人員所熟悉的語(yǔ)法處理集合。在包的摘要中對(duì)包中的內(nèi)容解釋如下:“為流元素的函數(shù)式操作提供支持的類,如對(duì)集合的map-reduce轉(zhuǎn)換。”

下方的類圖提供了對(duì)該包的一個(gè)概覽,著重介紹了接下來(lái)的示例中將要用到的功能。包結(jié)構(gòu)中列示了大量的Builder類。這些類與連貫接口一樣,可以將方法鏈接成為管道式的操作集。

字符串解析和集合處理雖然簡(jiǎn)單,在真實(shí)世界中仍有許多實(shí)際應(yīng)用場(chǎng)景。在進(jìn)行自然語(yǔ)言處理(NLP)時(shí),需要將句子分割為單獨(dú)的詞。生物信息學(xué)將DNA和RNA表示為有字母組成的堿基,如C,G,A,T或U。在每個(gè)問題領(lǐng)域中,字符串對(duì)象會(huì)被分解,然后針對(duì)其各個(gè)組成部分進(jìn)行操作、過濾、計(jì)數(shù)以及排序等操作。因此,盡管示例中所包含的用例十分簡(jiǎn)單,其理念仍適用于各類有實(shí)際意義的任務(wù)。

下方的示例代碼解析了一個(gè)包含一個(gè)句子的字符串對(duì)象,并統(tǒng)計(jì)單詞的數(shù)量和感興趣的字母。包括空白行在內(nèi),整個(gè)代碼清單的行數(shù)不超過70行。

  1. import java.util.*; 
  2.  
  3. import static java.util.Arrays.asList; 
  4. import static java.util.function.Function.identity; 
  5. import static java.util.stream.Collectors.*; 
  6.  
  7. public class Main { 
  8.  
  9.    public static void p(String s) { 
  10.        System.out.println(s.replaceAll("[\\]\\[]""")); 
  11.   } 
  12.  
  13.   private static List uniq(List letters) { 
  14.        return new ArrayList(new HashSet(letters)); 
  15.   } 
  16.  
  17.    private static List sort(List letters) { 
  18.        return letters.stream().sorted().collect(toList()); 
  19.    } 
  20.  
  21.    private static  Map uniqueCount(List letters) { 
  22.        return letters.stream(). 
  23.                collect(groupingBy(identity(), counting())); 
  24.    } 
  25.  
  26.    private static String getWordsLongerThan(int length, List words) { 
  27.        return String.join(" | ", words 
  28.                        .stream().filter(w -> w.length() > length) 
  29.                        .collect(toList()) 
  30.        ); 
  31.    } 
  32.  
  33.    private static String getWordLengthsLongerThan(int length, List words) 
  34.    { 
  35.        return String.join(" | ", words 
  36.                .stream().filter(w -> w.length() > length) 
  37.                .mapToInt(String::length) 
  38.                .mapToObj(n -> String.format("%" + n + "s", n)) 
  39.                .collect(toList())); 
  40.    } 
  41.  
  42.    public static void main(String[] args) { 
  43.  
  44.        String s = "The quick brown fox jumped over the lazy dog."
  45.        String sentence = s.toLowerCase().replaceAll("[^a-z ]"""); 
  46.  
  47.        List words = asList(sentence.split(" ")); 
  48.        List letters = asList(sentence.split("")); 
  49.  
  50.        p("Sentence : " + sentence); 
  51.        p("Words    : " + words.size()); 
  52.        p("Letters  : " + letters.size()); 
  53.  
  54.        p("\nLetters  : " + letters); 
  55.        p("Sorted   : " + sort(letters)); 
  56.        p("Unique   : " + uniq(letters)); 
  57.  
  58.        Map m = uniqueCount(letters); 
  59.        p("\nCounts"); 
  60.  
  61.        p("letters"); 
  62.        p(m.keySet().toString().replace(",""")); 
  63.        p(m.values().toString().replace(",""")); 
  64.  
  65.        p("\nwords"); 
  66.        p(getWordsLongerThan(3, words)); 
  67.        p(getWordLengthsLongerThan(3, words)); 
  68.     } 

示例程序執(zhí)行輸出:

Sentence : the quick brown fox jumped over the lazy dog
Words    : 9
Letters  : 44

Letters  : t, h, e,  , q, u, i, c, k,  , b, r, o, w, n,  , f, o, x,  , j, u, m, p, e, d,  , o, v, e, r,  , t, h, e,  , l, a, z, y,  , d, o, g
Sorted   :  ,  ,  ,  ,  ,  ,  ,  , a, b, c, d, d, e, e, e, e, f, g, h, h, i, j, k, l, m, n, o, o, o, o, p, q, r, r, t, t, u, u, v, w, x, y, z
Unique   :  , a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, t, u, v, w, x, y, z

Counts
letters
  a b c d e f g h i j k l m n o p q r t u v w x y z
8 1 1 1 2 4 1 1 2 1 1 1 1 1 1 4 1 1 2 2 2 1 1 1 1 1

words
quick | brown | jumped | over | lazy
    5 |     5 |      6 |    4 |    4

上述代碼已經(jīng)經(jīng)過了多重精簡(jiǎn)。其中一些方式并非在各個(gè)版本的Java中都可行,而且有些方式可能并不符合公認(rèn)的編碼風(fēng)格指南。思考一下在較早版本的Java中如何才能夠獲得相同的輸出?首先,需要?jiǎng)?chuàng)建許多局部變量用于臨時(shí)存儲(chǔ)數(shù)據(jù)或作為索引。其次,需要通過許多條件語(yǔ)句和循環(huán)告知Java如何處理數(shù)據(jù)。新的函數(shù)式編程方式更加專注于需要什么數(shù)據(jù),而并不關(guān)心與其相關(guān)的臨時(shí)變量、嵌套循環(huán)、索引管理或條件語(yǔ)句的處理。

在某些情況下,采用早期版本中的標(biāo)準(zhǔn)Java語(yǔ)法以減少代碼量是以犧牲清晰度為代價(jià)的。例如,示例代碼***行的標(biāo)準(zhǔn)import語(yǔ)句中的Java包引用了java.util下的所有類,而不是根據(jù)類名分別引用。對(duì)System.out.println的調(diào)用被替換為對(duì)一個(gè)名為p的方法的調(diào)用,這樣在每次方法調(diào)用時(shí)都可以使用短名稱(行9-11)。由于可能違反某些Java的編碼規(guī)范,這些改變富有爭(zhēng)議,不過有著其他背景的程序開發(fā)人員查看這些代碼時(shí)可能并不會(huì)有何問題。

另外一些情況下,則利用了從JDK8預(yù)覽版才新增的功能特性。靜態(tài)引用(行3-5)可以減少內(nèi)聯(lián)所需引用的類的數(shù)量。而正則表達(dá)式(行10,45)則可以用與函數(shù)式編程本身無(wú)關(guān)的方式,有效隱藏循環(huán)和條件語(yǔ)句。這些習(xí)語(yǔ),特別是正則表達(dá)式的使用,經(jīng)常會(huì)因?yàn)殡y以閱讀和說(shuō)明而受到質(zhì)疑。如果運(yùn)用得當(dāng),這些習(xí)語(yǔ)可以減少噪音的數(shù)量,并且能夠限制開發(fā)人員需要閱讀和說(shuō)明的代碼數(shù)量。

***,示例代碼利用了JDK 8中新增的Streaming API。使用了Streaming API中大量的方法對(duì)列表進(jìn)行過濾、分組和處理(行17-40)。盡管在IDE中它們與內(nèi)附類的關(guān)聯(lián)關(guān)系很清晰,不過除非你已經(jīng)很熟悉這些API,否則這種關(guān)系并不是那么顯而易見。下表展示了示例代碼中所出現(xiàn)的每一次方法調(diào)用的來(lái)源。

方法

完整的方法名稱引用

stream()

java.util.Collection.stream()

sorted()

java.util.stream.Stream.sorted()

collect()

java.util.stream.Stream.collect()

toList()

java.util.stream.Collectors.toList()

groupingBy()

java.util.stream.Collectors.groupingBy()

identity()

java.util.function.Function.identity()

counting()

java.util.stream.Collectors.counting()

filter()

java.util.stream.Stream.filter()

mapToInt()

java.util.stream.Stream.mapToInt()

mapToObject()

java.util.stream.Stream.mapToObject()

uniq()(行13)和sort()(行17)方法體現(xiàn)了同名的Unix實(shí)用工具的功能。sort引入了對(duì)流的***次調(diào)用,首先對(duì)流進(jìn)行排序,然后再將排序后的結(jié)果收集到列表中。UniqueCount()(行21)與uniq -c類似,返回一個(gè)map對(duì)象,其中每個(gè)鍵是一個(gè)字符,每個(gè)值則是這個(gè)字符出現(xiàn)次數(shù)的統(tǒng)計(jì)。兩個(gè)“getWords”方法(行26和行33)用于過濾出比給定長(zhǎng)度短的單詞。getWordLengthsLongerThan()方法調(diào)用了一些額外的方法,將結(jié)果格式化并轉(zhuǎn)換成不可修改的String對(duì)象。

整段代碼并未引入任何與Lambda表達(dá)式相關(guān)的新概念。之前所介紹的語(yǔ)法只適用于Java Stream API特定的使用場(chǎng)景。

總結(jié)

用更少的代碼實(shí)現(xiàn)同樣任務(wù)的理念與愛因斯坦的理念一致:“必須盡可能地簡(jiǎn)潔明了,但又不能簡(jiǎn)單地被簡(jiǎn)單。”Lambda表達(dá)式和新的Stream API因其能夠?qū)崿F(xiàn)擴(kuò)展性良好的簡(jiǎn)潔代碼而備受關(guān)注。它們讓程序開發(fā)人員可以恰當(dāng)?shù)貙⒋a簡(jiǎn)化成***的表現(xiàn)形式。

函數(shù)式編程習(xí)語(yǔ)的設(shè)計(jì)理念就是簡(jiǎn)短,而且仔細(xì)思考一下就會(huì)發(fā)現(xiàn)許多可以讓Java代碼更加精簡(jiǎn)的場(chǎng)景。新的語(yǔ)法雖然有點(diǎn)陌生但并非十分復(fù)雜。這些新的功能特性清晰地表明,作為一種語(yǔ)言,Java已經(jīng)遠(yuǎn)遠(yuǎn)超越其最初的目標(biāo)。它正在用開放的態(tài)度接受其他程序設(shè)計(jì)語(yǔ)言中最出色的一些功能,并將它們整合到Java之中。

責(zé)任編輯:倪明
相關(guān)推薦

2017-10-24 15:28:27

PHP代碼簡(jiǎn)潔SOLID原則

2018-09-18 16:20:08

Asyncjavascript前端

2022-08-31 08:19:04

接口returnCode代碼

2021-05-06 20:03:00

JavaStream代碼

2022-09-02 08:17:40

MapStruct代碼工具

2023-11-16 18:17:13

Python編程內(nèi)置模塊

2011-04-06 10:52:51

Java異常處理

2022-01-14 08:08:11

Java依賴沖突

2012-07-05 09:37:04

Java程序員

2019-06-27 10:32:57

Java開發(fā)代碼

2012-08-01 09:38:17

代碼整潔

2012-06-04 10:34:17

Lisp

2022-06-27 06:23:23

代碼編程

2022-12-15 10:52:26

代碼開發(fā)

2023-09-22 12:04:53

Java代碼

2011-02-22 16:31:45

微軟IE9HTML

2017-02-28 15:08:08

架構(gòu)微服務(wù)數(shù)據(jù)庫(kù)

2021-04-25 11:31:45

React代碼整潔代碼的實(shí)踐

2022-08-31 12:15:09

JavaScript代碼優(yōu)化

2014-07-21 14:40:43

Android內(nèi)存
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)