面向?qū)ο蟮囊恍┲R(shí)暫時(shí)告一段落,從本文開始墅茉,進(jìn)入java語法的重學(xué)階段~
初識(shí)數(shù)組
什么是數(shù)組
數(shù)組:相同類型的伟阔、用一個(gè)標(biāo)識(shí)符名稱封裝到一起的一個(gè)對(duì)象序列或基本類型數(shù)據(jù)序列。
數(shù)組的定義及初始化
定義及動(dòng)態(tài)初始化
- 方式一筹淫,java推薦用法: type [] 變量名 = new type[數(shù)組中元素的個(gè)數(shù)];
//舉例
int[] a = new int[10];
for (int i = 0; i < a.length; i++){
a[i] = new Random().nextInt();
}
- 方式二,c語言用法(不推薦): type 變量名 [] = new type[數(shù)組中元素的個(gè)數(shù)];
int a[] = new int[10];
for (int i = 0; i < a.length; i++){
a[i] = new Random().nextInt();
}
以上兩種方式都叫做動(dòng)態(tài)初始化呢撞,也就是說损姜,只有當(dāng)程序運(yùn)行以后,你才能知道數(shù)組里到底存了哪些數(shù)據(jù)狸相。方式二的命名方式c和c++程序員比較熟悉薛匪,但是java官方推薦使用第一種捐川,一看就能知道脓鹃,這是一個(gè)int型的數(shù)組,叫a古沥。
靜態(tài)初始化
int[] b = new int[]{1,2,3};
在定義數(shù)組的時(shí)候直接初始化瘸右,大括號(hào)里的值就是數(shù)組的值。
隱式初始化
int[] c = {1,2,3};
可以不寫new岩齿,直接使用大括號(hào)初始化太颤,但是本質(zhì)上還是調(diào)用了new的,只是可以不寫出來而已盹沈,所以叫隱式初始化龄章。
最后,我們回過頭來仔細(xì)的研究一下下面這一句代碼:
int[] a = new int[10];
這句代碼做了哪些事呢乞封?
- int[] a: 定義了一個(gè)int型數(shù)組的引用做裙,名字叫做a,存放在棧中肃晚。
- new int[10]:初始化一個(gè)長(zhǎng)度為10的int型數(shù)組锚贱,在堆中開辟相應(yīng)大小的內(nèi)存。
- int[] a = new int[10]:將堆中開辟的數(shù)組的內(nèi)存地址賦給數(shù)組引用a关串。
這樣就可以通過a這個(gè)變量拧廊,來操作這個(gè)數(shù)組了监徘。
是不是覺得這個(gè)過程很熟悉?沒錯(cuò)吧碾!我們創(chuàng)建一個(gè)對(duì)象的過程也是這樣的凰盔!那這是不是證明,數(shù)組其實(shí)是一個(gè)對(duì)象呢倦春?我們后面會(huì)詳細(xì)分析廊蜒。
數(shù)組的使用
數(shù)組自身的使用
數(shù)組是使用方式大家應(yīng)該都很清楚了,我這里簡(jiǎn)單的提一下溅漾。
數(shù)組的遍歷
- 方式一:for循環(huán)
for (int i = 0; i < myList.length; i++) {
System.out.println(myList[i] + " ");
}
- 方式二:foreach循環(huán)
for (int element: myList) {
System.out.println(element);
}
數(shù)組長(zhǎng)度
int length = myList.length;
java中的每個(gè)數(shù)組都有一個(gè)名為length的屬性山叮,表示數(shù)組的長(zhǎng)度。
length屬性我們后面會(huì)詳細(xì)分析添履。
數(shù)組元素不為基本數(shù)據(jù)類型
數(shù)組是可以存放任意類型的數(shù)據(jù)的屁倔,不一定非得是基本數(shù)據(jù)類型。數(shù)組元素不為基本原生數(shù)據(jù)類型時(shí)暮胧,存放的是引用類型锐借,而不是對(duì)象本身。當(dāng)生成對(duì)象之后往衷,引用才指向?qū)ο蟪瑁駝t引用為null。
Person[] p = new Person[3];
//未生成對(duì)象時(shí)席舍,引用類型均為空
System.out.println(p[0]);
//生成對(duì)象之后布轿,引用指向?qū)ο? p[0] = new Person(10);
p[1] = new Person(20);
p[2] = new Person(30);
for(int i = 0; i < p.length; i++){
System.out.println(p[i].age);
}
數(shù)組作為方法的參數(shù)
public void printArray(int[] array) {
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
}
數(shù)組作為方法的返回值
public int[] reverse(int[] list) {
int[] result = new int[list.length];
for (int i = 0, j = result.length - 1; i < list.length; i++, j--) {
result[j] = list[i];
}
return result;
}
數(shù)組內(nèi)容的輸出
首先,這樣寫是不對(duì)的来颤。
public static void main(String[] args) {
int a[]={1,9};
System.out.println(a.toString());
}
//[I@61bbe9ba
這輸出的是什么奇怪的東西汰扭?我們先不管,后面會(huì)詳細(xì)說福铅。那怎么輸出數(shù)組呢萝毛?
方式一:
public static void main(String [] args){
int a[]={1,9};
for (int i : a){
System.out.println(i);
}
}
方式二:
public static void main(String [] args){
int a[]={1,9};
System.out.println(Arrays.toString(a));
}
數(shù)組內(nèi)容的比較
數(shù)組內(nèi)容的比較可以使用equals()方法嗎?
看代碼:
public class ArrayTest{
public static void main(String[] args){
int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
System.out.println(a.equals(b));
//結(jié)果是false滑黔。
}
}
所以證明不能直接用equals()方法比較數(shù)組內(nèi)容笆包,因?yàn)闆]有override Object中的實(shí)現(xiàn),所以仍采用其實(shí)現(xiàn)略荡,即采用==實(shí)現(xiàn)equals()方法庵佣,比較是否為同一個(gè)對(duì)象。
Object類中的equals方法默認(rèn)使用==實(shí)現(xiàn)的撞芍,至于為什么數(shù)組也能使用equals方法秧了,我們后面再分析。
怎么比較呢序无?一種解決方案是自己寫代碼验毡,另一種方法是利用java.util.Arrays衡创。
java.util.Arrays中的方法全是static的。其中包括了equals()方法的各種重載版本晶通。
代碼如下:
import java.util.Arrays;
public class ArrayEqualsTest{
public static boolean isEquals(int[] a, int[] b){
if( a == null || b == null ){
return false;
}
if(a.length != b.length){
return false;
}
for(int i = 0; i < a.length; ++i ){
if(a[i] != b[i]){
return false;
}
}
return true;
}
public static void main(String[] args){
int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
System.out.println(isEquals(a,b));
System.out.println(Arrays.equals(a,b));
}
}
Arrays類的使用
java.util.Arrays 類能方便地操作數(shù)組璃氢,它提供的所有方法都是靜態(tài)的。
具有以下功能:
- 給數(shù)組賦值:通過 fill 方法狮辽。
- 對(duì)數(shù)組排序:通過 sort 方法,按升序一也。
- 比較數(shù)組:通過 equals 方法比較數(shù)組中元素值是否相等。
- 查找數(shù)組元素:通過 binarySearch 方法能對(duì)排序好的數(shù)組進(jìn)行二分查找法操作喉脖。
- .......
我覺得這些大家也都知道椰苟,我就不細(xì)說了,重點(diǎn)在后面树叽。
數(shù)組的高級(jí)應(yīng)用
二維數(shù)組
二維數(shù)組是數(shù)組的數(shù)組舆蝴。其實(shí)java只有一維數(shù)組,但是由于數(shù)組可以存放任意類型的數(shù)據(jù)题诵,當(dāng)然也就可以存放數(shù)組了洁仗,這個(gè)時(shí)候,就可以模擬多維數(shù)組了性锭。
基本的定義方式同樣有兩種赠潦,如:
type[][] i = new type[2][3];//(推薦)
type i[][] = new type[2][3];
變長(zhǎng)的二維數(shù)組
二維數(shù)組的每個(gè)元素都是一個(gè)一維數(shù)組,這些數(shù)組不一定都是等長(zhǎng)的草冈。
聲明二維數(shù)組的時(shí)候可以只指定第一維大小她奥,空缺出第二維大小,之后再指定不同長(zhǎng)度的數(shù)組疲陕。但是注意方淤,第一維大小不能空缺(不能只指定列數(shù)不指定行數(shù))钉赁。
public class ArrayTest4{
public static void main(String[] args){
//二維變長(zhǎng)數(shù)組
int[][] a = new int[3][];
a[0] = new int[2];
a[1] = new int[3];
a[2] = new int[1];
//Error: 不能空缺第一維大小
//int[][] b = new int[][3];
}
}
二維數(shù)組也可以在定義的時(shí)候初始化蹄殃,使用花括號(hào)的嵌套完成,這時(shí)候不指定兩個(gè)維數(shù)的大小你踩,并且根據(jù)初始化值的個(gè)數(shù)不同诅岩,可以生成不同長(zhǎng)度的數(shù)組元素。
int[][] c = new int[][]{{1, 2, 3},{4},{5, 6, 7, 8}};
可變參數(shù)
有的時(shí)候带膜,你需要一個(gè)方法吩谦,但是你在調(diào)用它之前不知道要傳遞幾個(gè)參數(shù)給他,這個(gè)時(shí)候你就需要可變參數(shù)了膝藕。
public static void main(String [] args){
System.out.println(add(2,3));
System.out.println(add(2,3,5));
}
public static int add(int x,int ...args){
int sum=x;
for(int i=0;i<args.length;i++){
sum+=args[i];
}
return sum;
}
那個(gè)奇怪的int ...args
就是可變參數(shù)式廷,這樣你就可以傳遞任意個(gè)你想傳遞的數(shù)據(jù)了。
java把可變參數(shù)當(dāng)做數(shù)組處理芭挽。
注意:可變參數(shù)必須位于最后一項(xiàng)滑废。當(dāng)可變參數(shù)個(gè)數(shù)多余一個(gè)時(shí)蝗肪,必將有一個(gè)不是最后一項(xiàng),所以只支持有一個(gè)可變參數(shù)蠕趁。因?yàn)閰?shù)個(gè)數(shù)不定薛闪,所以當(dāng)其后邊還有相同類型參數(shù)時(shí),java無法區(qū)分傳入的參數(shù)屬于前一個(gè)可變參數(shù)還是后邊的參數(shù)俺陋,所以只能讓可變參數(shù)位于最后一項(xiàng)豁延。
可變參數(shù)實(shí)質(zhì)上是一個(gè)數(shù)組,所以下面這樣重載是不可以的腊状!
private int sumUp(int... values) {
}
private int sumUp(int[] values) {
}
盡管在背地里诱咏,編譯器會(huì)把能匹配不確定個(gè)實(shí)參的形參,轉(zhuǎn)化為數(shù)組形參缴挖;而且也可以用數(shù)組包了實(shí)參胰苏,再傳遞給實(shí)參個(gè)數(shù)可變的方法;但是醇疼,這并不表示“能匹配不確定個(gè)實(shí)參的形參”和“數(shù)組形參”完全沒有差異硕并。
一個(gè)明顯的差異是,如果按照調(diào)用實(shí)參個(gè)數(shù)可變的方法的形式秧荆,來調(diào)用一個(gè)最后一個(gè)形參是數(shù)組形參的方法倔毙,只會(huì)導(dǎo)致一個(gè)“cannot be applied to”的編譯錯(cuò)誤。
比如:
private static void testOverloading(int[] i) {
System.out.println("A");
}
public static void main(String[] args) {
testOverloading(1, 2, 3);//編譯出錯(cuò)
}
這樣是不行的乙濒。
除此之外陕赃,可變參數(shù)是不可以使用泛型的,關(guān)于泛型颁股,我們下一篇文章會(huì)詳細(xì)講解么库。
可變參數(shù)還有許多其他的坑,感興趣的可以詳細(xì)了解一下甘有,我就不多說了诉儒。畢竟。亏掀。打字好累啊忱反。
數(shù)組復(fù)制
int[] a = new int[]{1,2};
int[] b = a;
b [1] = 5;
這個(gè)時(shí)候a[1]也變成了5,為什么會(huì)這樣滤愕?就不用我多說了吧温算,所以,要拷貝一個(gè)數(shù)組间影,還是需要些技巧的:
方式一:System.arraycopy的用法
int[] src = {1,3,5,7,9,11,13,15,17};
int[] dest = {2,4,6,8,10,12,14,16,18,20};
//從src中的第一個(gè)元素起復(fù)制三個(gè)元素注竿,即1,3,5復(fù)蓋到dest第2個(gè)元素開始的三個(gè)元素
System.arraycopy(src, 0, dest, 1, 3);
System.out.println(Arrays.toString(dest));
//[2, 1, 3, 5, 10, 12, 14, 16, 18, 20]
方式二:Arrays.copyOf的用法
int[] src = {1,3,5,7,9,11,13,15,17};
int[] dest = {2,4,6,8,10,12,14,16,18,20};
//copyOf(是復(fù)制src數(shù)組從0開始的兩個(gè)元素到新的數(shù)組對(duì)象)
int[] copyof=Arrays.copyOf(src, 2);
System.out.println(Arrays.toString(copyof));
//[1, 3]
方式三:Arrays.copyOfRange的用法
nt[] src = {1,3,5,7,9,11,13,15,17};
int[] dest = {2,4,6,8,10,12,14,16,18,20};
//copyRange(從src數(shù)組中從0開始的第二個(gè)元素到第五個(gè)元素復(fù)制到新數(shù)組巩割,含頭不含尾)
int[] copyofRange=Arrays.copyOfRange(src, 2,6);
System.out.println(Arrays.toString(copyofRange));
//[5, 7, 9, 11]
數(shù)組到底是什么
說了那么多胰丁,那么,數(shù)組究竟是個(gè)什么東西呢喂分?
我們來看看數(shù)組有沒有什么可以用的方法:
喲锦庸,還真有?怎么看著這么像Object類里那幾個(gè)方法啊!這其中蒲祈,必有蹊蹺甘萧。
來看這段代碼:
public class Test {
public static void main(String[] args) {
int[] array = new int[10];
System.out.println("array的父類是:" + array.getClass().getSuperclass());
System.out.println("array的類名是:" + array.getClass().getName());
}
}
//array的父類是:class java.lang.Object
//array的類名是:[I
從上面示例可以看出,數(shù)組的是Object的直接子類,它屬于“第一類對(duì)象”,但是它又與普通的java對(duì)象存在很大的不同梆掸,從它的類名就可以看出:[I扬卷,這是什么東東?酸钦?
我們?cè)倏慈缦率纠?/p>
public class Test {
public static void main(String[] args) {
int[] array_00 = new int[10];
System.out.println("一維數(shù)組:" + array_00.getClass().getName());
int[][] array_01 = new int[10][10];
System.out.println("二維數(shù)組:" + array_01.getClass().getName());
int[][][] array_02 = new int[10][10][10];
System.out.println("三維數(shù)組:" + array_02.getClass().getName());
}
}
//一維數(shù)組:[I
//二維數(shù)組:[[I
//三維數(shù)組:[[[I
通過這個(gè)實(shí)例我們知道:[代表了數(shù)組的維度怪得,一個(gè)[表示一維,兩個(gè)[表示二維卑硫⊥搅担可以簡(jiǎn)單的說數(shù)組的類名由若干個(gè)'['和數(shù)組元素類型的內(nèi)部名稱組成。不清楚我們?cè)倏矗?/p>
public class Test {
public static void main(String[] args) {
System.out.println("Object[]:" + Object[].class);
System.out.println("Object[][]:" + Object[][].class);
System.err.println("Object[][][]:" + Object[][][].class);
System.out.println("Object:" + Object.class);
}
}
//Object[]:class [Ljava.lang.Object;
//Object[][]:class [[Ljava.lang.Object;
//Object[][][]:class [[[Ljava.lang.Object;
//Object:class java.lang.Object
從這個(gè)實(shí)例我們可以看出數(shù)組的“廬山真面目”欢伏。同時(shí)也可以看出數(shù)組和普通的Java類是不同的入挣,普通的java類是以全限定路徑名+類名來作為自己的唯一標(biāo)示的,而數(shù)組則是以若干個(gè)[+L+數(shù)組元素類全限定路徑+類來最為唯一標(biāo)示的硝拧。這個(gè)不同也許在某種程度上說明了數(shù)組也普通java類在實(shí)現(xiàn)上存在很大的區(qū)別径筏,也許可以利用這個(gè)區(qū)別來使得JVM在處理數(shù)組和普通java類時(shí)作出區(qū)分。
我們?cè)趈dk中并沒有找到一個(gè)可以代表數(shù)組的類障陶,但是數(shù)組的的確確是Object類的一個(gè)子類滋恬,那么,它究竟是從哪冒出來的呢抱究?
數(shù)組是對(duì)象
首先恢氯,數(shù)組是對(duì)象!
但是這個(gè)數(shù)組對(duì)象并不是從某個(gè)類實(shí)例化來的媳维,而是由JVM直接創(chuàng)建的酿雪,因此查看類名的時(shí)候會(huì)發(fā)現(xiàn)是很奇怪的樣子,這個(gè)直接創(chuàng)建的對(duì)象的父類就是Object侄刽,所以可以調(diào)用Object中的所有方法,包括你用到的toString()朋凉。
所以我們之前的輸出問題就很明顯了州丹,因?yàn)檎{(diào)用的toString()方法是來自于Object的,這個(gè)方法的實(shí)現(xiàn)是
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
所以就打出了類似于[I@61bbe9ba這樣的稀奇古怪的數(shù)字。
如果要輸出“{1,9}”這樣的內(nèi)容墓毒,可以寫一個(gè)循環(huán)逐個(gè)輸出吓揪,或者使用Arrays.toString()輸出。
數(shù)組的length屬性也是jvm添加的所计,數(shù)組一初始化柠辞,jvm就會(huì)給它一個(gè)固定的length【屬性】,在它的生命周期中不可變主胧。
數(shù)組的協(xié)變
java中數(shù)組為什么要設(shè)計(jì)為協(xié)變的叭首?
比如:
Number[] num = new Integer[10];
num[0] = 2.1;
這樣的語句可以通過編譯,而在運(yùn)行時(shí)會(huì)錯(cuò)誤踪栋。
那為何不禁止數(shù)組協(xié)變焙格,在編譯期間就指出錯(cuò)誤呢?
因?yàn)镾E5之前還沒有泛型夷都,但很多代碼迫切需要泛型來解決問題眷唉。
舉個(gè)例子,比較兩個(gè)數(shù)組是否“值相等“的Arrays.equals( )方法囤官。因?yàn)榈讓訉?shí)現(xiàn)調(diào)用的是Object.equals( )方法冬阳,和數(shù)組中元素的具體類型無關(guān)。
for (int i=0; i<length; i++) {
Object o1 = a[i];
Object o2 = a2[i];
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
所以不想讓每個(gè)類型都要重新定義Arrays.equals( )方法党饮。而是”泛化“地接受任何元素類型的數(shù)組為參數(shù)摩泪,就像現(xiàn)在這樣:
public static boolean equals(Object[] a, Object[] a2) {
... ...
}
要讓Object[]能接受所有數(shù)組類型,那個(gè)時(shí)候又沒有泛型劫谅,最簡(jiǎn)單的辦法就是讓數(shù)組接受協(xié)變见坑,把String[],Integer[]都定義成Object[]的派生類捏检,然后多態(tài)就起作用了荞驴。
但為什么數(shù)組設(shè)計(jì)成”協(xié)變“不會(huì)有大問題呢?這是基于數(shù)組的一個(gè)獨(dú)有特性:
數(shù)組記得它內(nèi)部元素的具體類型贯城,并且會(huì)在運(yùn)行時(shí)做類型檢查熊楼。
這就是上面的代碼能通過編譯厂庇,但運(yùn)行時(shí)報(bào)錯(cuò)的原因:
Number[] num = new Integer[10];
num[0] = 2.1; //Error
num變量記得它內(nèi)部元素是Integer驼侠。所以運(yùn)行時(shí)給它插入double型的時(shí)候不讓執(zhí)行。
這反而是數(shù)組的優(yōu)點(diǎn)杠人,也是當(dāng)初”敢于“把數(shù)組設(shè)計(jì)成協(xié)變的原因踩晶。雖然向上轉(zhuǎn)型以后执泰,編譯期類型檢查放松了,但因?yàn)閿?shù)組運(yùn)行時(shí)對(duì)內(nèi)部元素類型看得緊渡蜻,不匹配的類型還是插不進(jìn)去的术吝。
這也是為什么容器Collection不能設(shè)計(jì)成協(xié)變的原因计济。Collection不做運(yùn)行時(shí)類型檢查,比較耿直排苍。還是題主Number的例子沦寂,如果Collection接受”協(xié)變“,List<Integer>的引用能傳給List<Number>:
List<Integer> integerList = new ArrayList<Integer>();
List<Number> num = integerList; // 假設(shè)現(xiàn)在容器接受”協(xié)變“
這時(shí)候我想往List<Number>里插入一個(gè)Double淘衙。它不會(huì)像數(shù)組這樣”堅(jiān)貞“传藏,它將”安靜“地接受。
num.add(new Double(2.1));
然后當(dāng)我們從原先的integerList里面取東西彤守,才會(huì)發(fā)現(xiàn)出問題了毯侦。雖然看上去從integerList里取Integer,我們的操作無可指責(zé)遗增。但取出來的卻是Double型叫惊。
Integer itg=integerList.get(0); //BOOM!
于其到拿出來之后才發(fā)現(xiàn)不對(duì)做修,那還不如當(dāng)初就不讓插入霍狰。這就是數(shù)組的好處。
而且饰及,在引入了通配符(Wildcard)之后蔗坯,協(xié)變的功能也已經(jīng)被實(shí)現(xiàn)了。而且配合通配符的”上界“和”下界“一起用燎含,容器內(nèi)元素的類型還是受到嚴(yán)格控制的宾濒,雖然有點(diǎn)復(fù)雜。
List<? extends Number> derivedNum=new ArrayList<Integer>();
所以總的來說屏箍,雖然數(shù)組的協(xié)變不是一個(gè)完美的設(shè)計(jì)绘梦,但也不能算非常爛。起碼還能用赴魁,沒有捅出大簍子卸奉。而且數(shù)組又不支持泛型,底層類庫到處是Object[]颖御,現(xiàn)在也不可能改了榄棵。
數(shù)組不支持泛型
比如:
List<String>[] l = new ArrayList<String>[10];
會(huì)報(bào)錯(cuò),無法編譯通過
根本的原因是:數(shù)組在創(chuàng)建的時(shí)候必須知道內(nèi)部元素的類型潘拱,而且一直都會(huì)記得這個(gè)類型信息疹鳄,每次往數(shù)組里添加元素,都會(huì)做類型檢查芦岂。
但因?yàn)镴ava泛型是用擦除(Erasure)實(shí)現(xiàn)的瘪弓,運(yùn)行時(shí)類型參數(shù)會(huì)被擦掉。所以對(duì)于泛型數(shù)組盔腔,編譯器看不到泛型的String類型參數(shù)杠茬。數(shù)組由于無法確定所持有元素的類型月褥,所以不允許初始化弛随。
具體我們會(huì)在下一篇《泛型》中詳細(xì)說明瓢喉。
內(nèi)存中的數(shù)組
數(shù)組的內(nèi)存模型
- 一維數(shù)組:
int arr[] = new int[3];
- 二維數(shù)組:
int[ ][ ] arr = new int[3][ ];
arr[0] = new int[3];
arr[1] = new int[5];
arr[2] = new int[4];
總結(jié)
- 數(shù)組的定義推薦使用
int[] a
方式。 - 數(shù)組的長(zhǎng)度是不可變的舀透。
- 數(shù)組是特殊的對(duì)象栓票,父類是Object類。
- java不支持泛型數(shù)組愕够。
- 數(shù)組是協(xié)變的走贪。
- 數(shù)組中可以保存任意類型的數(shù)據(jù),從而可以創(chuàng)建多維數(shù)組惑芭。
本篇文章就到這里坠狡。如果文章內(nèi)容有什么錯(cuò)誤或者更好的理解,請(qǐng)及時(shí)與我聯(lián)系遂跟。
本文首發(fā)自我的個(gè)人博客:
地址:http://wpblog.improvecfan.cn/
同步更新于csdn:
地址:http://blog.csdn.net/qq_31655965
同步更新于簡(jiǎn)書:
地址:http://www.reibang.com/u/8dc5811b228f
轉(zhuǎn)載請(qǐng)注明出處L友亍!;盟?痢!哄尔!
看完了假消,如果對(duì)你有用,隨心后點(diǎn)個(gè)贊唄~
引用:
《java編程思想》
《java核心卷一》
https://www.zhihu.com/question/21394322
http://www.cnblogs.com/jjdcxy/p/5870524.html
http://blog.csdn.net/renfufei/article/details/15503469
http://www.cnblogs.com/chenssy/p/3463719.html