數(shù)據(jù)類型
Java是一種強類型語言篙贸,即意味著必須為每一個變量聲明一種類型禽篱。在Java中一共有8種基本數(shù)據(jù)類型八千,其中有4種整型慷吊、2種浮點類型袖裕、1種用于表示Unicode編碼的字符單元的字符類型char和一種用于表示真值的boolean類型。
1) 整型
整型用于表示沒有小數(shù)部分的值溉瓶,它允許是負數(shù)急鳄,Java提供了4種整型:
在通常情況下,int類型最常用。如果要表示星球上居住的人數(shù)堰酿,就需要使用long類型了疾宏。byte和short類型用于特定的應(yīng)用場合,比如底層的文件處理或者需要控制占用存儲空間量的大數(shù)組触创。
整型的直接量默認是int坎藐,即2表示int類型的2,為了表示一個long型的整型直接量嗅榕,在其后追加字母L或l即可(建議使用L,以免和數(shù)字1混淆)顺饮。語句byte b = 128
會造成編譯錯誤,因為128是整型直接量且超過了byte的取值范圍凌那。
默認情況下兼雄,整型直接量是一個十進制整數(shù)。要表示一個二進制整數(shù)直接量帽蝶,使用0b或0B開頭;表示一個八進制整數(shù)直接量赦肋,使用0開頭;表示一個十六進制整數(shù)直接量,使用0x或0X開頭励稳。
為了提高可讀性,Java允許在數(shù)值直接量的兩個數(shù)字之間使用下劃線,例如long ssn = 232_45_4519
Java沒有任何無符號(unsigned)形式的int佃乘、long、short或byte類型
十進制整數(shù)轉(zhuǎn)其他進制整數(shù):Integer.toString(int number, int radix)
返回一個String
其他進制整數(shù)轉(zhuǎn)十進制:Integer.parseInt(String s, int radix)
返回類型為int
2)浮點類型
浮點類型用于表示有小數(shù)部分的數(shù)值驹尼,Java提供了2種浮點類型:
double表示這種類型的數(shù)值精度是float的兩倍,float稱為單精度型,double稱為雙精度型趣避。通常情況下,應(yīng)該使用double型,因為它比float型更精確。
可以以E或e為指數(shù)用科學(xué)計數(shù)法表示浮點數(shù),例如1.2345E+2,在十六進制中,則使用p表示指數(shù)而不是e新翎,且尾數(shù)采用十六進制時指數(shù)的基數(shù)是2而不是10
浮點數(shù)直接量是double型,即5.0被認為是double型的,可以通過追加f或F表示float型直接量,當(dāng)然也可以在浮點數(shù)值后面添加后綴D或d表示double型(雖然沒有必要多此一舉)程帕。如果float接受的是一個整數(shù),不需要加f或者F地啰,但是如果是小數(shù)一定要加f或者F愁拭。
常量Double.POSITIVE_INFINITY、Double.NEGATIVE_INFINITY和Double.NaN(以及相應(yīng)的Float類型的常量)分別表示正無窮大亏吝、負無窮大和不是一個數(shù)岭埠。例如,一個正整數(shù)除以0的結(jié)果為正無窮大。計算0/0或者負數(shù)的平方根結(jié)果為NaN惜论。
不能用如下的方式檢測一個特定的值是否等于Double.NaN:
if(x == Double.NaN) // is never true
應(yīng)該改成
if(Double.isNaN(x)) // check whether x is "not a number"
浮點數(shù)在運算時會產(chǎn)生一定誤差,如果對精度有極高要求许赃,應(yīng)該使用BigDecimal類。
strictfp 關(guān)鍵字
strictfp, 即 strict float point (精確浮點)来涨。
strictfp 關(guān)鍵字可應(yīng)用于類图焰、接口或方法启盛。使用 strictfp 關(guān)鍵字聲明一個方法時蹦掐,該方法中所有的float和double表達式都嚴格遵守FP-strict的限制,符合IEEE-754規(guī)范。當(dāng)對一個類或接口使用 strictfp 關(guān)鍵字時僵闯,該類中的所有代碼卧抗,包括嵌套類型中的初始設(shè)定值和代碼,都將嚴格地進行計算鳖粟。嚴格約束意味著所有表達式的結(jié)果都必須是 IEEE 754 算法對操作數(shù)預(yù)期的結(jié)果社裆,以單精度和雙精度格式表示。
示例1
// Example of precision control with strictfp
public strictfp class MyClass{
public MyClass(){}
public static void main(String[] args){
float aFloat = 0.6710339f;
double aDouble = 0.04150553411984792d;
double sum = aFloat + aDouble;
float quotient = (float)(aFloat / aDouble);
System.out.println("float: " + aFloat);
System.out.println("double: " + aDouble);
System.out.println("sum: " + sum);
System.out.println("quotient: " + quotient);
}
}
輸出結(jié)果
float: 0.6710339
double: 0.04150553411984792
sum: 0.71253945297742238
quotient: 16.1673355
示例2
// Example of precision control with strictfp:
public class MyClass2{
public float aFloat;
public double aDouble;
public MyClass2(){}
public strictfp double add(float a, double b){
return (a + b);
}
public static void main(String[] args){
MyClass2 myClass2 = new MyClass2();
myClass2.aFloat = 0.6710339f;
myClass2.aDouble = 0.04150553411984792d;
double sum = myClass2.add(myClass2.aFloat, myClass2.aDouble);
System.out.println("float: " + myClass2.aFloat);
System.out.println("double: " + myClass2.aDouble);
System.out.println("sum: " + sum);
}
}
輸出結(jié)果
float: 0.6710339
double: 0.04150553411984792
sum: 0.71253945297742238
如果你想讓你的浮點運算更加精確向图,而且不會因為不同的硬件平臺所執(zhí)行的結(jié)果不一致的話泳秀,可以用關(guān)鍵字strictfp.
3)Unicode和char類型
Java中字符采用Unicode編碼(統(tǒng)一的字符編號,僅僅提供字符與編號間映射榄攀。符號數(shù)量在不斷增加嗜傅,已超百萬),Unicode又有不同的UTF(即Unicode轉(zhuǎn)換格式檩赢,定義Unicode中編號的編碼方式)吕嘀,常用的有UTF-16和UTF-8,其中UTF-8為變長表示贞瞒,長度可能為1~6個字節(jié)偶房;UTF-16為變長表示,長度可能是2或4個字節(jié)军浆。
我們先來明確幾個概念:
內(nèi)碼:某種語言運行時棕洋,其char和string在內(nèi)存中的編碼方式。
外碼:除了內(nèi)碼乒融,皆是外碼掰盘。
碼點:Unicode編碼中一個字符對應(yīng)的二進制數(shù)。
代碼單元:在UTF-16編碼中簇抵,用char表示的十六位二進制數(shù)庆杜,占兩個字節(jié)。
要注意的是碟摆,源代碼編譯產(chǎn)生的目標(biāo)代碼文件(可執(zhí)行文件或class文件)中的編碼方式屬于外碼晃财。
JVM中內(nèi)碼采用UTF-16。早期,UTF-16采用固定長度2字節(jié)的方式編碼断盛,兩個字節(jié)可以表示65536種符號(其實真正能表示要比這個少)罗洗,足以表示當(dāng)時Unicode中所有字符,也就是說當(dāng)時一個碼點就對應(yīng)一個代碼單元钢猛,即每個Unicode字符都用一個char表示伙菜,一個16位的Unicode碼以\u開頭的4位十六進制表示,范圍從'\u0000'到'\uFFFF',范圍是0~65535命迈。但是隨著Unicode中字符的增加贩绕,2個字節(jié)無法表示所有的字符,UTF-16采用了2字節(jié)或4字節(jié)的方式來完成編碼壶愤。Java為應(yīng)對這種情況淑倾,考慮到向前兼容的要求,Java用一對char來表示那些需要4字節(jié)的字符征椒。所以娇哆,Java中的char固定占用兩個字節(jié)(即一個代碼單元),大多數(shù)常用Unicode字符使用一個代碼單元表示勃救,而輔助Unicode字符需要兩個代碼單元來表示碍讨,即一個碼點由一個或兩個代碼單元組成。
String的length()方法返回的是采用UTF-16編碼表示的給定字符串所需要的代碼單元數(shù)量蒙秒,它在一些情況下不等于字符串中實際的字符數(shù)勃黍,length()是一個較為底層的方法。
如果要得到實際的字符數(shù)(即碼點數(shù)量),可以調(diào)用:
int cpCount = str.codePointCount(0,str.length());
調(diào)用str.charAt(n)將返回位置n的代碼單元税肪,n介于0~str.length()-1之間溉躲。要想獲得第i個碼點,應(yīng)該使用下列語句:
int index = str.offsetByCodePoints(0,i);
int cp = str.codePointAt(index);
更多詳見:Java中char占幾個字節(jié)
char類型的字面量值要用單引號括起來。例如:'A'是編碼值為65所對應(yīng)的字符常量益兄。它與"A"不同锻梳,"A"是包含一個字符A的字符串。char類型可以表示為十六進制值净捅,范圍從'\u0000'到'\uFFFF'
有一些用于表示特殊字符的轉(zhuǎn)義序列,如下:
注意 \r 和 \n 的區(qū)別疑枯,前者叫回車(Carriage Return),后者叫新行(New Line)蛔六,但是都會造成換行荆永。不同操作系統(tǒng)的行分隔符不同,可用System.getProperty("line.separator")來獲取當(dāng)前OS的換行符
不同系統(tǒng)的換行符為:
\r Mac
\n Unix/Linux
\r\n Windows
注釋中的\u也會起轉(zhuǎn)義作用,如下:
// \u00A0 is a newline
(\u00A0會被替換成換行符)
// Look inside c:\users
(會產(chǎn)生編譯錯誤,因為\u后面未跟著4個十六進制數(shù))
下面是判斷一個字符是否是漢字的方法:
public static boolean isChineseChar(char c){
try {
return String.valueOf(c).getBytes("UTF-8").length > 1;
}
catch (UnsupportedEncodingException e) {
return false;
}
}
將字符c先用String.valueOf轉(zhuǎn)換為字符串国章,然后使用getBytes("UTF-8")將字符串按照UTF-8編碼格式轉(zhuǎn)換為字節(jié)數(shù)組具钥,漢字的字節(jié)數(shù)會大于1,即可判斷(如果直接對String使用length得到的是字符數(shù)不是字節(jié)數(shù))。但是可能會拋出UnsupportedEncodingException液兽,要進行捕獲處理骂删。
4) boolean類型
boolean類型有兩個值:false和true,用來判定邏輯條件。不同于C/C++中0代表false宁玫,非0代表true粗恢,Java中整型值和布爾值之間不能進行相互轉(zhuǎn)換。
比如,下面的語句在C/C++中是允許的,表示一個無限循環(huán):
while(1){
do something
}
但是在Java中不允許這么做,可以改為:
while(true){
do something
}
可以打印boolean類型的變量或者布爾表達式欧瘪,會呈現(xiàn)true或者false
數(shù)據(jù)類型轉(zhuǎn)換
將一個小范圍類型變量轉(zhuǎn)化為大范圍類型的變量稱為拓寬類型眷射,反之稱為縮窄類型。把小范圍類型變量賦值給大范圍類型的變量或小范圍類型變量和大范圍類型變量共同參與運算,Java會自動拓寬類型佛掖。而如果要縮窄類型妖碉,必須顯式完成。
注意:
1.類型轉(zhuǎn)換不改變被轉(zhuǎn)換的變量苦囱,例如嗅绸,下面的代碼中的d在類型轉(zhuǎn)換之后值不變:
double d = 4.5;
int i = (int)d; // i becomes 4, but d is still 4.5
2.x1 op= x2形式的增強賦值表達式的執(zhí)行為x1 = (T)(x1 op x2),T是x1的類型。因此撕彤,下面代碼是正確的:
int sum = 0;
sum += 4.5;// 等價于sum = (int)(sum + 4.5)
3.將一個int型變量賦值給short型或byte型的變量,必須顯式地使用類型轉(zhuǎn)換猛拴,如下面的語句會產(chǎn)生編譯錯誤:
int i = 1;
byte b = i; // Error because explicit casting is required
然而如果整型直接量在目標(biāo)變量允許的范圍內(nèi)羹铅,那么將整型直接量賦給short型或byte型就不需要顯式類型轉(zhuǎn)換,如:
byte b = 1;
4.字符型數(shù)據(jù)和數(shù)值型數(shù)據(jù)之間的轉(zhuǎn)換:
char 型數(shù)據(jù)可以轉(zhuǎn)換成任意一種數(shù)值類型愉昆,反之亦然。將整數(shù)轉(zhuǎn)換成 char 型數(shù)據(jù)時,只用到該數(shù)據(jù)的低十六位韩肝,其余部分都被忽略砰碴。例如:
char ch = (char)0XAB0041; /* The lower 16 bits hex code 0041
is assigned to ch*/
System.out.println(ch); // ch is character A
注意:如果數(shù)值類型的值表示范圍在0~65535之間,可以隱式轉(zhuǎn)換為char芳室,但如果超過65535就需要強制類型轉(zhuǎn)換专肪,char會截取數(shù)據(jù)的低十六位。
當(dāng)一個char 型數(shù)據(jù)轉(zhuǎn)換成數(shù)值型時堪侯,這個字符的Unicode碼就被轉(zhuǎn)換成某個特定的數(shù)值類型嚎尤。
int i = (int)'A'; // Decimal 65 is assigned to ch
System.out.println(i) // i is 65
如果char的Unicode值未超過數(shù)值型范圍,可以隱式轉(zhuǎn)換伍宦,否則也要強制類型轉(zhuǎn)換芽死。如:
byte b = 'A'; //is OK,b = 65
byte c = (byte)'\uFFF4'; //超過byte范圍,必須強轉(zhuǎn)
變量
變量用于表示在程序中可能被改變的值次洼。變量聲明告知編譯器根據(jù)數(shù)據(jù)類型為變量分配合適的內(nèi)存空間关贵。變量聲明的語法如下:
datatype variableName;
如果幾個變量為同一類型,允許一起聲明它們:
datatype variable1, variable2, ..., variablen;
可以在聲明變量的同時初始化,也可以先聲明后初始化:
int count = 1; // 聲明同時初始化變量
int count;
count = 1; //先聲明卖毁,后初始化
常量
常量是一個賦值后保持不變的量,用final關(guān)鍵字修飾揖曾,在類中定義的常量一般用static final修飾。常量必須在同一條語句中聲明和賦值,不可先聲明再賦值翩肌。
使用常量有三個好處:
1)不必重復(fù)輸入同一個值
2)如果必須修改常量的值模暗,只需在源代碼的一處改動
3)給常量賦一個描述性的名字會提高程序的易讀性
數(shù)值操作符
數(shù)值數(shù)據(jù)類型的操作符包括標(biāo)準(zhǔn)的算術(shù)操作符:加號(+)、減號(-)念祭、乘號(*
)兑宇、除號( / )、求余號(%)
注意:
1.如果被除數(shù)是負數(shù)粱坤,結(jié)果是負數(shù);如果除數(shù)是負數(shù)被除數(shù)是正數(shù)結(jié)果是正數(shù);如果都是負數(shù)其結(jié)果就是負數(shù)隶糕。如 -7 % 3 = -1, -26 % -8 = -2,20 % -13 = 7,即無論正負,商和除數(shù)乘積的絕對值不能超過被除數(shù)的絕對值。
2.如果是兩個byte short int long相除站玄,得到結(jié)果如果是浮點數(shù)枚驻,小數(shù)位全部舍去保留整數(shù)部分。
3.byte short int long除以0會報異常java.lang.ArithmeticException: / by zero
4.float double除以0得到正無窮和負無窮株旷。
System.out.println(1.0f/0); //正無窮
System.out.println(-1/0.0); //負無窮
System.out.println(0.0/0); //NaN
增強賦值操作符
x1 op= x2形式的增強賦值表達式的執(zhí)行為x1 = (T)(x1 op x2),T是x1的類型再登。其中op可以是加號(+)、減號(-)晾剖、乘號(*
)锉矢、除號( / )、求余號(%)
自增和自減操作符
分為++var齿尽、--var沽损、var++、var--四種循头,加減號決定給var加1還是減1绵估,前置還是后置符號決定先更新后使用值還是先使用值后更新
關(guān)系運算符
Java中有一系列用于比較關(guān)系的運算符:==(等于)、!=(不等于)卡骂、<(小于)国裳、>(大于)、<=(小于等于)偿警、>=(大于等于)
邏輯操作符
邏輯操作符!(非)躏救、&&(與)、||(或)和^(異或)可以用于產(chǎn)生復(fù)合型布爾表達式螟蒸,邏輯操作符被稱為短路操作符或懶惰操作符盒使,即按順序執(zhí)行表達式,如果某一步已經(jīng)可以判斷整個表達式的真假七嫌,不再繼續(xù)執(zhí)行少办,否則繼續(xù)執(zhí)行。
位運算符
處理整型類型時诵原,可以直接對組成整型數(shù)值的各個位完成操作英妓。位運算符包括:&(按位與)挽放、|(按位或)、^(按位異或)蔓纠、~(按位取反)辑畦、<<(左移,高位舍棄腿倚,低位補0)纯出、>>(右移,低位舍棄敷燎,高位用符號位填充)暂筝、>>>(右移,低位舍棄硬贯,高位0填充)
注意:
- 移位運算符的右操作數(shù)要完成模32的運算(除非左操作數(shù)是long類型焕襟,在這種情況下右操作數(shù)要模64),例如1
<<
35等價于1<<
3 - & 、| 和 ^ 也可以用在布爾表達式中饭豹,此時它們是邏輯操作符鸵赖,但不會短路,不推薦使用
- 可以使用掩碼技術(shù)得到一個數(shù)二進制的某一位:
int fourthBitFromRight = (n & 0b1000) / 0b1000
上式將n的右數(shù)第4位保留墨状,將其他位掩掉卫漫,再除以0b1000,就得到了該位上的數(shù)
選擇
Java中的選擇語句類型有:單分支if語句肾砂、雙分支if-else語句、嵌套if語句宏悦、多分支if-else語句镐确、switch語句、條件表達式
1) 單分支if語句
if(布爾表達式){
語句(組);
}
分支中如果只有單條語句可以省略外圍花括號饼煞,否則不能省略
2) 雙分支if-else語句
if(布爾表達式){
布爾表達式為真時執(zhí)行的語句(組);
}
else{
布爾表達式為假時執(zhí)行的語句(組);
}
嵌套層數(shù)沒有限制源葫,但為了程序可讀性,盡量不要進行過多的嵌套砖瞧,且嵌套語句應(yīng)有適當(dāng)?shù)目s進保持層次關(guān)系息堂。
3) 嵌套的if語句和多分支的if-else語句
下面是一個嵌套的if語句,if(j > k)嵌套在語句if(i > k)內(nèi)
if(i > k) {
if(j > k)
System.out.println("i and j greater than k");
}
else
System.out.println("i is less than or equal to k");
下面是一個多分支的if-else語句
if(score >= 90.0)
System.out.print("A");
else{
if(score >= 80.0)
System.out.print("B");
else{
if(score >= 70.0)
System.out.print("C");
else{
if(score >= 60.0)
System.out.print("D");
else
system.out.print("E");
}
}
}
為了可讀性块促,建議改寫成如下形式:
if(score >= 90.0)
System.out.print("A");
else if(score >= 80.0)
System.out.print("B");
else if(score >= 70.0)
System.out.print("C");
else if(score >= 60.0)
System.out.print("D");
else
System.out.print("E");
注意:只有在前面的所有條件都為false才測試下一個條件
4) switch語句
switch語句常用于多分支的選擇問題:
switch(switch表達式){
case value1: 語句(組)1;
break;
case value2: 語句(組)2;
break;
...
case valueN: 語句(組)N;
break;
default: 當(dāng)沒有一個給出的case與switch表達式匹配時執(zhí)行的語句(組)
}
注意:
- switch表達式可以為char荣堰、byte、short竭翠、int或者String型值(從 Java 7 開始振坚,可以在 switch 條件判斷語句中使用 String 對象。整型中不支持long和浮點型斋扰,是因為 switch 的設(shè)計初衷是對那些只有少數(shù)的幾個值進行等值判斷渡八,如果值過于復(fù)雜啃洋,那么還是用 if 比較合適),并且總要用括號括住
- value1,...,valueN必須與switch表達式具有相同的數(shù)據(jù)類型,且是常量表達式屎鳍,不能出現(xiàn)變量宏娄,例如:x、y+1等
- 當(dāng)switch表達式的值與case語句匹配時,執(zhí)行從該case開始的語句逮壁,直到遇到一個break語句或到達switch語句的結(jié)束孵坚。break語句是可選的,會立即終止switch語句
- default語句是可選的,當(dāng)沒有一個給出的case與switch表達式匹配時執(zhí)行default語句指定的操作貌踏,如果不加default語句十饥,就什么也不做
5) 條件表達式
條件表達式基于一個條件計算表達式的值,它是Java中唯一的三元操作符祖乳。
boolean-expression ? expression1 : expression2;
//(布爾表達式? 表達式1:表達式2)
如果布爾表達式的值為true逗堵,則條件表達式的結(jié)果為表達式1;否則,結(jié)果為表達式2眷昆。
例如:
System.out.println((num % 2 == 0) ? "num is even" : "num is odd");
注意冒號兩邊是表達式蜒秤,不能是其他操作。
循環(huán)
1) 塊作用域
塊(即復(fù)合語句)是指由一對大括號括起來的若干條簡單的Java語句亚斋。塊確定了變量的作用域作媚,變量只在包含自己的塊中可見。一個塊可以嵌套在另一個塊中帅刊。例如:
public static void main(String[] args)
{
int n;
. . .
{
int k;
. . .
} // k is only defined up to here
}
但是不能聲明兩個作用域(生命周期)重疊的同名變量纸泡,例如下面的語句會產(chǎn)生編譯錯誤,這是因為前面定義的n的作用域是從定義處開始到方法末尾赖瞒,后面定一個的n的作用于是從定義處到代碼塊末尾女揭,兩者作用于發(fā)生了重疊:
public static void main(String[] args)
{
int n;
. . .
{
int k;
int n;//Erro -- can't redefine n in inner block
. . .
}
}
這與C++不同,在C++中允許在重疊的作用域定義同名變量栏饮,后定義會覆蓋先定義的變量吧兔。但在Java中并不允許這么做。
2) while循環(huán)
while循環(huán)在條件為真的情況下袍嬉,重復(fù)地執(zhí)行語句:
while(循環(huán)繼續(xù)條件){
//循環(huán)體
語句(組);
}
當(dāng)程序不幸出現(xiàn)了死循環(huán)境蔼,如果是從命令窗口運行程序的,按CTRL+C鍵來結(jié)束
3) do-while循環(huán)
do-while循環(huán)和while循環(huán)基本一樣伺通,不同的是while循環(huán)是前測循環(huán)箍土,即先檢測循環(huán)條件后執(zhí)行循環(huán)體;do-while是后測循環(huán),即先執(zhí)行循環(huán)體后檢測循環(huán)條件泵殴。只有在一開始就不滿足循環(huán)繼續(xù)條件時涮帘,兩種循環(huán)的執(zhí)行次數(shù)不同,即while循環(huán)不執(zhí)行笑诅,do-while循環(huán)執(zhí)行一次调缨。否則兩種循環(huán)的執(zhí)行次數(shù)相同疮鲫。
do{
// 循環(huán)體;
語句(組);
}while(循環(huán)繼續(xù)條件);
注意do-while循環(huán)后面的分號不要丟!
4) for循環(huán)
for循環(huán)的基本語法為:
for(初始操作;循環(huán)繼續(xù)條件;每次迭代后的操作) {
//循環(huán)體
語句(組);
}
初始動作可以是0個或是多個以逗號隔開的變量聲明語句或賦值表達式:
int i = 0;
for( ;i < 100;i++){
System.out.println("Welcome to Java!");
}// 將初始動作省略弦叶,放在循環(huán)語句之前執(zhí)行
for(int m = 0,n = 0; m + n < 10; m++,n++){
System.out.println("Welcome to Java!");
}// 多個初始化動作
每次迭代后的操作也可以是0個或多個逗號隔開的語句:
for(int i = 0;i < 100; ){
System.out.println("Welcome to Java!");
i++;
}// 將每次迭代后的操作放入循環(huán)體內(nèi)
for(int i = 1;i < 100;System.out.println(i),i++);
// 每次迭代后執(zhí)行多個操作
下面的三種循環(huán)寫法是等價的:
for( ; ; ){
//do something
}
for( ;true; ){
//do something
}
while(true){
//do something
}
5) for-each循環(huán)
Java有一種很強的循環(huán)結(jié)構(gòu)俊犯,可以用來依次處理數(shù)組中的每個元素(其他類型的元素集合亦可)而不必為指定的下標(biāo)值而分心。
這種增強的for循環(huán)的語句格式為:
for(variable : collection) statement
定義一個變量用于暫存集合中的每一個元素伤哺,并執(zhí)行相應(yīng)的語句(組)燕侠,collection這一集合表達式必須是一個數(shù)組或者是一個實現(xiàn)了Iterable接口的類對象(例如ArrayList)。
for-each循環(huán)只能用于按順序遍歷數(shù)組或集合的情況立莉,如果要使用其他順序绢彤,應(yīng)該使用其他循環(huán)語句
6) break和continue
continue跳出本次迭代進入下一次迭代,break跳出整個循環(huán)蜓耻。
雖然不提倡使用goto語句茫舶,但偶爾使用goto語句跳出循環(huán)還是有益處的。Java中提供了類似于C++中g(shù)oto語句的帶標(biāo)簽的break語句和continue語句刹淌,用于跳出多重嵌套的循環(huán)語句饶氏。
標(biāo)簽必須放在希望跳出的最外層循環(huán)之前,并且必須緊跟一個冒號有勾。另外要注意疹启,只能跳出語句塊,而不能跳入語句塊蔼卡。
下面的代碼使用了帶標(biāo)簽的break語句:
int i;
label1:
for( i = 0;i < 10;i ++) {
if(i == 5)
break label1;
}
System.out.println(i);// i = 5
上述代碼中喊崖,i在等于5時跳出循環(huán)到循環(huán)首部的標(biāo)簽label1位置,由于是帶標(biāo)簽的break語句雇逞,不再重新進入循環(huán)贷祈,而是跳過循環(huán)執(zhí)行下面的打印語句。
如果把改成帶標(biāo)簽的continue語句:
int i;
label2:
for( i = 0;i < 10;i ++) {
if(i == 5)
continue label2;
}
System.out.println(i); // i = 10
上述代碼中喝峦,i在等于5時也跳出循環(huán)到循環(huán)首部的標(biāo)簽label2位置,但由于是帶標(biāo)簽的continue語句呜达,會重新進入循環(huán)谣蠢。
枚舉類型
有時,變量的取值只在一個有限集合內(nèi)查近。例如:銷售的服裝或比薩餅只有小眉踱、中、大霜威、超大這四種尺寸谈喳。此時可以給每種尺寸編號為1、2戈泼、3婿禽、4,但是為了程序的可讀性赏僧,可以定義一個枚舉類。
可以把枚舉類看作普通類扭倾,它們都可以定義一些屬性和方法淀零,也可以添加public等訪問修飾符,不同之處是:枚舉類不能使用 extends 關(guān)鍵字繼承其他類膛壹,因為 枚舉類已經(jīng)繼承了 java.lang.Enum<T>
(java是單一繼承),其中T是定義的枚舉類類型驾中,也就是說一個枚舉類T的類型其實是<T extends Enum<T>>
。Enum類是一個抽象類模聋。
下面定義一個簡單的枚舉類:
public enum Size {SMALL, MEDIUM, LARGE, EXTRA_LARGE};
其中enum是定義枚舉類的關(guān)鍵字肩民,可類比普通類的class。Size是枚舉類名链方,類比普通類名持痰。
SMALL、MEDIUM侄柔、LARGE共啃、EXTRA_LARGE是枚舉實例,為枚舉類的靜態(tài)常量暂题,相當(dāng)于 public static final Type CONSTANT 移剪。static關(guān)鍵字被省略,類型為Size薪者,可以用Size.枚舉實例名
來訪問纵苛,命名習(xí)慣同常量。Size變量只能存儲枚舉類中定義的枚舉值或null言津,一個enum類的構(gòu)造方法限制是private的攻人,也就是不允許我們調(diào)用,所以不要構(gòu)造新的Size類型對象悬槽。
除了預(yù)先定義的靜態(tài)常量怀吻,還可以在枚舉類中添加一些構(gòu)造器、方法和域初婆。當(dāng)然蓬坡,構(gòu)造器只是在構(gòu)造枚舉常量的時候使用,在枚舉常量后加上括號可給構(gòu)造器傳參磅叛,如果不加括號則會調(diào)用無參構(gòu)造器屑咳。下面是一個示例:
public enum Size
{
SMALL("S"),MEDIUM("M"),LARGE("L"),EXTRA_LARGE("XL");
private String abbreviation;
private Size(String abbreaviation){
this.abbreviation = abbreviation;
}
public String getAbbreviation() {return abbreviation};
}
注意:枚舉實例序列(注意是序列,所以各個枚舉實例用逗號隔開弊琴,最后以分號結(jié)尾)的聲明必須是枚舉類定義的第一條語句兆龙。枚舉類的構(gòu)造器必須為private,保證了構(gòu)造器只能用于枚舉類中定義的枚舉值的構(gòu)造敲董,而不讓客戶代碼構(gòu)造新的枚舉值紫皇。當(dāng)訪問枚舉值時慰安,構(gòu)造方法被調(diào)用,枚舉值構(gòu)造方法中的參數(shù)被賦值給Abbreviation坝橡。如:
public class TestSize{
public static void main(String[] args) {
Size size = Size.LARGE;
System.out.println(size.getAbbreviation());
}
結(jié)果打印出"L"
枚舉類型的每一個值都將映射到 protected Enum(String name, int ordinal)構(gòu)造函數(shù)中泻帮,在這里,每個枚舉值的名稱都被轉(zhuǎn)換成一個字符串计寇,且按照在枚舉類中出現(xiàn)的先后次序锣杂,從0開始進行編號。
下面是枚舉類的常用API:
- int ordinal()
返回enum聲明中枚舉常量的位置番宁,位置從0開始計數(shù) - int compareTo(
<T extends Enum<T>>
o)
按照序號(枚舉類中的定義次序元莫,即ordinal返回值)比較此枚舉與指定對象的順序,小于返回一個負值蝶押,絕對值是兩者的序號差;等于返回0;大于返回一個正值踱蠢,絕對值是兩者的序號差 - boolean equals(
<T extends Enum<T>>
o)
比較兩個枚舉常量是否相等,可以用==代替 - String toString()
返回枚舉常量的名稱 - static
<T extends Enum<T>>
valueOf(Class<T>
enumType, String name)
返回帶指定名稱的指定枚舉類型的枚舉常量(是toString的逆操作) - static T[] values()
返回一個包含全部枚舉值的數(shù)組
例如:
int index = Size.SMALL.ordinal();
//index是0
int cmp = Size.SMALL.compareTo(Size.MEDIUM);
//cmp是-1
boolean isEqual = Size.SMALL.equals(Size.MEDIUM);
//isEqual為false
String enumName = Size.SMALL.toString();
//enumName是"SMALL"
Size s = Enum.valueof(Size.class,"SMALL");
//s是Size.SMALL
Size[] values = Size.values();
/*返回一個包含Size.SMALL,Size.MEDIUM,Size.LARGE,
Size.EXTRA_LARGE的數(shù)組 */
要比較兩個枚舉值是否相同,既可以使用equals也可以使用==
枚舉類型可以在一個類內(nèi)定義棋电,此時枚舉類被作為內(nèi)部類對待茎截。程序編譯后,將創(chuàng)建一個名為OuterClassName$EnumName
的字節(jié)碼文件赶盔。
可以在if或switch語句中使用枚舉變量企锌,例如:
if(size.equals(Size.SMALL){
// process SMALL
}
else if(size.equals(Size.MEDIUM){
// process MEDIUM
}
else
...
等價于:
switch(size){
case SMALL:
// process SMALL
break;
case MEDIUM:
// process MEDIUM
break;
...
}
在switch語句中,case標(biāo)簽是一個無限定的枚舉值(即SMALL于未,而不是Size.SMALL)
枚舉集合的使用:
java.util.EnumSet 和 java.util.EnumMap 是兩個枚舉集合撕攒。EnumSet 保證集合中的元素不重復(fù);EnumMap 中的 key是 enum 類型烘浦,而 value 則可以是任意類型抖坪。關(guān)于這個兩個集合的使用就不在這里贅述,可以參考 JDK 文檔闷叉。
更多用法見:Java枚舉(enum)詳解7種常見的用法
輸入輸出
1) 輸入
從控制臺讀取"標(biāo)準(zhǔn)輸入流"System.in擦俐,需要構(gòu)造一個Scanner對象,并與"標(biāo)準(zhǔn)輸入流"System.in關(guān)聯(lián)握侧。
Scanner in = new Scanner(System.in);
下面給出Scanner類的常用API:
- Scanner(InputStream in)
用給定的輸入流創(chuàng)建一個Scanner對象(System.in就是一個InputStream,表示系統(tǒng)標(biāo)準(zhǔn)輸入流捌肴,默認從鍵盤讀取輸入) - Scanner(File source)
用文件創(chuàng)建一個Scanner對象從文件讀取輸入,如果文件不存在會拋出FileNotFoundException - Scanner(String str)
用字符串創(chuàng)建一個Scanner對象從字符串讀取輸入 - String nextLine()
讀取輸入的下一行內(nèi)容(以回車作為分隔符) - String next()
讀取輸入的下一個字符串(以空白字符如空格藕咏、回車作為分割符) - String next(Pattern pattern)
讀取輸入的下一個字符串,進行正則驗證秽五,如果輸入不符合正則表達式會拋出InputMismatchException - int nextInt()
讀取下一個int - double nextDouble()
讀取下一個double() - boolean hasNext()
檢測輸入是否還有單詞 - boolean hasNext(Pattern pattern)
檢測輸入的數(shù)據(jù)是否符合指定的正則標(biāo)準(zhǔn) - boolean hasNextInt()
檢測輸入是否還有int - boolean hasDouble()
檢測輸入是否還有double - useDelimiter(String pattern)
修改輸入分隔符(如果用\n
作分隔符,next()就可以實現(xiàn)和nextLine()一樣的功能)
Scanner讀入時會有回車殘留的問題孽查!在使用除了nextLine()的其他方法(稱為標(biāo)記讀取方法)讀入時,本次讀入不會讀取分隔符坦喘,即空格盲再、Tab和回車等西设,但分隔符會進入緩沖區(qū),如果在標(biāo)記讀取方法之后調(diào)用nextLine()就會先讀取緩沖區(qū)的內(nèi)容答朋。使用nextLine()讀入贷揽,本次讀入則不會讀入行分隔符(回車),且回車不會進入緩沖區(qū)而是直接被舍棄梦碗,不影響下一次讀入禽绪。
行分隔符字符串是由系統(tǒng)定義的,在Windows平臺上是\r\n洪规,而在Linux|UNIX平臺上是\n印屁。為了得到特定平臺上的行分隔符,使用:String lineSeparator = System.getProperty("line.separator");
因為輸入是可見的斩例,所以Scanner類不適用于從控制臺讀取密碼雄人。Java SE 6特別在io包中引入了Console類實現(xiàn)不回顯的輸入。要想讀取一個密碼念赶,可以采用下列代碼:
Console cons = System.console();
if(cons != null) {
String username = cons.readLine("User name: ");
char[] passwd = cons.readPassword("Password: ");
cons.printf("Username is: " + username + "\n");
// 顯示用戶名
cons.printf("Password is: " + passwd + "\n");
// 顯示密碼
}
else {
System.out.println("Console is unavailable.");
// 提示無控制臺使用權(quán)限
}
幾點注意:
1.Console類不能用new構(gòu)造對象础钠,屬于單例模式,構(gòu)造方法被private修飾
2.為了安全起見叉谜,返回的密碼存放在一維字符數(shù)組中旗吁,而不是字符串中。在對密碼進行處理后正罢,應(yīng)該馬上用一個填充值覆蓋數(shù)組元素阵漏。
3.采用Console對象處理輸入不如Scanner方便,每次只能讀取一行輸入翻具,而沒有能夠讀取一個單詞或一個數(shù)值的方法履怯。
4.Java要與Console進行交互,不總是能得到可用的Java Console類的裆泳。一個JVM是否有可用的Console叹洲,依賴于底層平臺和JVM如何被調(diào)用。如果JVM是在交互式命令行(比如linux的終端或windows的cmd)中啟動的工禾,并且輸入輸出沒有重定向到另外的地方运提,那么就我們可以得到一個可用的Console實例。
當(dāng)用Eclipse或NetBean中運行以上代碼時Console中將會有以下文字輸出:
Console is unavailable.
表示Java程序無法獲得Console實例闻葵,是因為JVM不是在命令行中被調(diào)用的民泵,或者輸入輸出被重定向了。
下面給出Console類的常用API:
- static Console console()
返回一個Console對象 - static char[] readPassword(String prompt, Object...args)
顯示提示字符串prompt并讀取用戶輸入槽畔,直到輸入行結(jié)束,結(jié)果存放在字符數(shù)組中栈妆。args參數(shù)用來提供輸入格式。 - static String readLine(String prompt,Object...args)
顯示提示字符串prompt并讀取用戶輸入,直到輸入行結(jié)束鳞尔,結(jié)果存放在字符串中嬉橙。args參數(shù)用來提供輸入格式。
2) 輸出
可以使用 System.out.print(x) 將數(shù)值 x 輸出到控制臺上寥假。這條命令將以 x 對應(yīng)的數(shù)據(jù)類型所允許的最大非 0 數(shù)字位數(shù)打印輸出 x 市框。
例如:
double x = 10000.0 / 3.0;
System.out.print(x);
打印
3333.3333333333335
如果希望顯示美元、美分等符號糕韧, 則有可能會出現(xiàn)問題枫振。
在早期的 Java 版本中,格式化數(shù)值曾引起過一些爭議兔沃。慶幸的是蒋得,Java SE 5.0 沿用了 C語言庫函數(shù)中的 printf方法。例如乒疏,調(diào)用
System.out.printf("%8.2f",x);
可以用 8 個字符的寬度和小數(shù)點后兩個字符的精度打印 x额衙。也就是說,打印輸出一個空格和7 個字符怕吴, 如下所示:
3333.33
在 printf中窍侧,可以使用多個參數(shù), 例如:
System.out.printf("Hello, %s. Next year, you'll be %d", name, age);
每一個以 % 字符開始的格式說明符都用相應(yīng)的參數(shù)替換转绷。 格式說明符尾部的轉(zhuǎn)換符將指示被格式化的數(shù)值類型:f 表示浮點數(shù)伟件,s 表示字符串,d 表示十進制整數(shù)议经。
下表列出了所有轉(zhuǎn)換符:
另外斧账,還可以給出控制格式化輸出的各種標(biāo)志。例如煞肾,逗號
標(biāo)志增加了分組的分隔符咧织。即
System.out.printf("%,.2f", 10000.0 / 3.0);
打印
3,333.33
下表列出了用于printf的所有標(biāo)志
可以使用靜態(tài)的 String.format 方法創(chuàng)建一個格式化的字符串,而不打印輸出:
String message = String.format("Hello, %s. Next year, you'll be %d", name , age);
基于完整性的考慮籍救, 下面簡略地介紹 printf方法中日期與時間的格式化選項(已經(jīng)過時)习绢。在新代碼中, 應(yīng)當(dāng)使用 java.time 包的方法蝙昙。 不過你可能會在遺留代碼中看到 Date 類和相關(guān)的格式化選項闪萄。格式包括兩個字母, 以 t 開始奇颠, 以下表中的任意字母結(jié)束:
例如
System.out.printf("%tc", new Date());
這條語句將用下面的格式打印當(dāng)前的日期和時間:
Mon Feb 09 18:05:19 PST 2015
從上表可以看到败去,某些格式只給出了指定日期的部分信息。例如烈拒,只有日期或月份为迈。如果需要多次對日期操作才能實現(xiàn)對每一部分進行格式化的目的就太笨拙了三椿。為此,可以采用一個格式化的字符串指出要被格式化的參數(shù)索引葫辐,表示該處格式化的是待格式化參數(shù)列表的第幾個參數(shù)。索引必須緊跟在%后面伴郁, 并以$
終止耿战。 例如:
System.out.printf("%1$s %2$tB %2$te,%2$tY","Due date:",new Date());
打印
Due date: February 9, 2015
還可以選擇使用 < 標(biāo)志。它指示前面格式說明中的參數(shù)將被再次使用焊傅。也就是說剂陡,下列語句將產(chǎn)生與前面語句同樣的輸出結(jié)果:
System.out .printf("%s %tB %<te, %<tY", "Due date:", new Date());
注意:參數(shù)索引值從1開始,而不是從0開始狐胎,%1$
...對第一個參數(shù)格式化鸭栖。這就避免了與0標(biāo)志混淆。
現(xiàn)在握巢,已經(jīng)了解了 printf 方法的所有特性晕鹊。下表給出了格式說明符的語法圖:
3) 重定向語法
Java使用System.out(系統(tǒng)類的輸出流對象)來表示標(biāo)準(zhǔn)輸出設(shè)備,默認情況下是顯示器暴浦,而用System.in(系統(tǒng)類的輸入流對象)來表示標(biāo)準(zhǔn)輸入設(shè)備溅话,默認情況下是鍵盤。
有時歌焦,我們需要從文件而不是鍵盤讀入數(shù)據(jù)飞几,并希望將程序輸出結(jié)果保存到文件中而不是打印在控制臺上。此時独撇,可以在命令行利用Shell的重定向語法將任意文件關(guān)聯(lián)到System.in和System.out屑墨,例如下面的語句實現(xiàn)了從input.txt文件輸入并將程序輸出結(jié)果輸入output.txt:
java MyProg < input.txt > output.txt
本節(jié)只是介紹了最常用的輸入輸出方式,更多輸入輸出知識詳見:Java學(xué)習(xí)總結(jié)之Java IO系統(tǒng)
方法
1) 定義方法
下面先來看一個方法的定義纷铣,其作用是返回兩個整數(shù)中的較大者:
public static int max(int num1,int num2){
int result;
if(num1 > num2)
result = num1;
else
result = num2;
return result;
}
其中花括號前的部分是方法頭卵史,花括號包括的部分是方法體。方法頭包括修飾符(public static)关炼、返回值類型(int)程腹、方法名(max)、形式參數(shù)(int num1儒拂、int num2)寸潦。形式參數(shù)構(gòu)成參數(shù)列表,方法名和參數(shù)列表構(gòu)成方法簽名社痛。
對帶返回值的方法而言见转,return語句是必需的,且如果存在多個選擇分支蒜哀,要確保任何分支都有返回值斩箫。對于void方法,也可以在方法中使用return結(jié)束方法調(diào)用。
2) 調(diào)用方法
如調(diào)用上述max方法:
int z = max(x,y);
其中x,y是實際參數(shù)乘客。
每當(dāng)調(diào)用一個方法時狐血,系統(tǒng)會創(chuàng)建一個活動記錄(也稱為活動框架),用于保存方法中的參數(shù)和變量易核⌒僦活動記錄置于一個內(nèi)存區(qū)域中,稱為調(diào)用堆棧(call stack)牡直。調(diào)用堆棧也稱為執(zhí)行堆棧缀匕、運行時堆棧渴邦,或者一個機器堆棧醇滥,常簡稱為"堆棧"怔球。當(dāng)一個方法調(diào)用另一個方法時咽白,調(diào)用者的活動記錄保持不動踢步,一個新的活動記錄被創(chuàng)建用于被調(diào)用的新方法,一個新的記錄"入棧"盒延。一個方法結(jié)束返回到調(diào)用者時咙崎,相應(yīng)的活動記錄被釋放桩盲,其中的參數(shù)和變量被銷毀约急,棧頂?shù)挠涗?出棧"零远。堆棧的最底層活動記錄是main方法的記錄,當(dāng)整個程序結(jié)束厌蔽,main方法記錄"出棧",棧為空牵辣,程序結(jié)束。
當(dāng)調(diào)用帶參數(shù)的方法時奴饮,如果參數(shù)是基本數(shù)據(jù)類型纬向,實參的值傳遞給形參(即拷貝),這個過程稱為按值傳遞戴卜,無論形參在方法中是否改變逾条,實參都不受影響;如果參數(shù)是引用類型(包括對象、普通數(shù)組投剥、對象數(shù)組)师脂,則傳遞的是引用值,可以理解為傳共享江锨,形參和實參指向同一對象吃警,此時實際對象可能會被改變。
main方法也有參數(shù)啄育,是一個String數(shù)組酌心,可以在命令行里給main方法傳遞字符串參數(shù)(也可以通過eclipse傳遞參數(shù),在運行——運行配置——自變量里傳遞)挑豌。例如安券,下面的命令行用三個字符串a(chǎn)rg0墩崩、arg1、arg2啟動程序TestMain:
java TestMain arg0 arg1 arg2
其中arg0侯勉、arg1鹦筹、arg2都是字符串,但是在命令行中出現(xiàn)時不需要雙引號址貌,但如果字符串包含空格盛龄,就必須用雙引號括住。
當(dāng)調(diào)用main方法時芳誓,Java解釋器會創(chuàng)建一個數(shù)組存儲命令行參數(shù),然后將該數(shù)組的引用傳遞給args啊鸭。例如锹淌,如果調(diào)用有n個命令行參數(shù)的程序,Java解釋器創(chuàng)建一個如下所示的數(shù)組:
args = new String[n];
然后Java解釋器傳遞參數(shù)args去調(diào)用main方法
注意:如果命令行沒有傳遞參數(shù)赠制,那么使用new String[0]創(chuàng)建數(shù)組赂摆。在這種情況下args引用了一個長度為0的空數(shù)組,它的值不是null钟些,但是args.length是0
數(shù)組
Java和許多高級語言都提供了一種稱作數(shù)組的數(shù)據(jù)結(jié)構(gòu)烟号,可以用它來存儲一個元素個數(shù)固定且元素類型相同的有序集。
數(shù)組一旦被創(chuàng)建政恍,它的大小不能改變汪拥。使用一個數(shù)組引用變量,通過下標(biāo)來訪問數(shù)組中的元素篙耗。
1) 聲明和創(chuàng)建數(shù)組(以一維數(shù)組為例)
來看下面的語句:
elementType[] arrayRefVar = new elementType[arraySize];
//(元素類型[] 數(shù)組引用變量 = new 元素類型[數(shù)組大小])
該語句完成了三個操作:
1.elementType[] arrayRefVar
聲明了一個elementType類型的數(shù)組引用變量arrayRefVar
2.new elementType[arraySize]
創(chuàng)建了一個大小為arraySize的elementType的數(shù)組
3.=
把數(shù)組引用賦給數(shù)組引用變量
注意:
1.elementType[] arrayRefVar
只是聲明數(shù)組變量迫筑,并不在內(nèi)存中給數(shù)組分配任何空間,它只是創(chuàng)建一個對數(shù)組應(yīng)用的存儲位置宗弯,如果變量不包含對數(shù)組的引用脯燃,這個變量的值為null
2.new elementType[arraySize]
在內(nèi)存中給數(shù)組元素分配了存儲空間
3.一個數(shù)組變量看起來似乎是存儲了一個數(shù)組,但實際上它存儲的是只是數(shù)組的引用蒙保。
4.當(dāng)創(chuàng)建數(shù)組后辕棚,它的元素被賦予默認值,數(shù)值型基本數(shù)據(jù)類型的默認值為0,char型的默認值為'\u0000'(空字符邓厕,但長度為1),boolean型的默認值為false逝嚎,非基本數(shù)據(jù)類型的默認值均為null
5.與C++不同,Java允許動態(tài)開數(shù)組邑狸,即無需在編譯期就確定數(shù)組大小懈糯,可以在程序運行時決定數(shù)組大小并創(chuàng)建相應(yīng)大小的數(shù)組。
2) 初始化數(shù)組
1.逐一賦值
int[] myList = new int[5];
myList[0] = 1;
myList[1] = 2;
myList[2] = 3;
myList[3] = 4;
myList[4] = 5;
2.數(shù)組初始化語法
下面的語法可以給數(shù)組的前k個元素賦值:
elementType[] arrayRefVar = {value0, value1, .., valuek};
注意:在使用數(shù)組初始化語法時单雾,必須將聲明赚哗、創(chuàng)建和初始化放在一條語句中她紫,將它們分開會產(chǎn)生語法錯誤:
int[] myList;
myList = {1,2,3,4,5}; //Error
3) 訪問數(shù)組元素
可以用arrayRefVar.length得到數(shù)組長度,數(shù)組元素的下標(biāo)為0 ~ arrayRefVar.length - 1屿储』叨铮可以直接使用下標(biāo)隨機訪問數(shù)組元素:
arrayRefVar[index] (數(shù)組引用變量[下標(biāo)])
如果要打印數(shù)組,可以使用一個循環(huán)打印逐一數(shù)組元素够掠。如果是字符數(shù)組民褂,可以使用一條打印語句打印:
char[] city = {'B','e','i','j','i','n','g'};
System.out.println(city);
4) 復(fù)制數(shù)組
要將一個數(shù)組中的內(nèi)容復(fù)制到另一個中,如果使用=
直接賦值疯潭,如:
list2 = list1;
上述語句只是將list1的引用值復(fù)制給了list2赊堪,這條語句執(zhí)行后,list1和list2都指向了同一個數(shù)組竖哩,如果改變其中一者哭廉,另一者也會受到同樣的影響。list2原先所引用的數(shù)組不能再引用相叁,它就變成了垃圾遵绰,會被JVM自動回收。在Java中增淹,可以使用賦值語句復(fù)制基本類型的值椿访,但不能復(fù)制數(shù)組等引用類型的值。
復(fù)制數(shù)組的四種方法
1.申請一個新數(shù)組虑润,遍歷原數(shù)組逐一復(fù)制元素
2.使用System類的靜態(tài)方法arraycopy()
3.使用數(shù)組對象.clone()
返回一個數(shù)組克隆的引用
4.使用Arrays類的copyOf()方法
下面是四種復(fù)制數(shù)組的方法的效率比較成玫,非常有趣,看來要多讀讀JDK源碼-
參考博客:https://www.cnblogs.com/zhengbin/p/5671403.html
5) 匿名數(shù)組
來看下面的語法:
new elementType[] {value0,value1, ... ,valuek};
該語句創(chuàng)建了一個沒有顯式引用變量的數(shù)組并進行了初始化端辱,這樣的數(shù)組稱為匿名數(shù)組梁剔。注意匿名數(shù)組的方括號里不指定數(shù)組長度!
6) 可變長參數(shù)列表
可以把類型相同但個數(shù)可變的參數(shù)傳遞給方法,語法如下:
typeName...parameterName (類型名...參數(shù)名)
注意:
1.在方法聲明中舞蔽,指定類型后緊跟著省略號(...)
2.只能給方法中指定一個可變長參數(shù)荣病,且該參數(shù)必須是最后一個參數(shù),任何常規(guī)參數(shù)必須在它之前
3.Java將可變長參數(shù)當(dāng)成數(shù)組對待渗柿,當(dāng)用數(shù)目可變的參數(shù)調(diào)用方法時个盆,Java會創(chuàng)建一個數(shù)組并把參數(shù)傳給它。所以可以傳入一個數(shù)組朵栖,但反之如果參數(shù)是數(shù)組類型颊亮,不能傳遞可變長參數(shù)。且參數(shù)為數(shù)組和可變長參數(shù)的兩個方法(其他參數(shù)均相同)不能重載陨溅,因為它們被認為是同一方法终惑。
4.如果有多個重載的方法都滿足被調(diào)用的條件,帶可變長參數(shù)的方法最后考慮被調(diào)用门扇。
7) Arrays類
Arrays類中包含了許多對處理數(shù)組的方法
下面是Arrays類的常用API:
如果計算機有多個處理器雹有,可以使用parallelSort偿渡,比sort更高效。
8) 多維數(shù)組
以二維數(shù)組為例霸奕,二維數(shù)組引用變量有三種表示方法:
elementType arrayRefVar[][]
elementType[] arrayRefVar[]
elementType[][] arrayRefVar
推薦使用elementType[][] arrayRefVar
聲明二維數(shù)組引用變量溜宽。
初始化語法也適用于多維數(shù)組:
int[][] array = {
{1, 2},
{3, 4}
};
等價于:
int[][] array = new int[2][2];
array[0][0] = 1;
array[0][1] = 2;
array[1][0] = 3;
array[1][1] = 4;
二維數(shù)組其實是一個數(shù)組,它的每個元素都是一個一維數(shù)組质帅,即它是數(shù)組的數(shù)組适揉。
x.length可以獲取二維數(shù)組的第一維長度,x[index].length可以獲取index行對應(yīng)的第二維長度煤惩。如果沒有初始化二維數(shù)組二維數(shù)組的所有元素默認為null嫉嘀,因為二維數(shù)組的元素是數(shù)組類型,默認值為null
二維數(shù)組中的每一行本身就是一個數(shù)組魄揉,因此吃沪,各行的長度可以不同。這樣的數(shù)組稱為鋸齒數(shù)組什猖,例如:
int[][] triangleArray = {
{1, 2, 3, 4, 5},
{2, 3, 4, 5},
{3, 4, 5},
{4, 5},
{5}
};
其余沒有賦值的部分并不會被賦為默認值,就是未分配空間,如果進行訪問會拋出ArrayIndexOutOfBoundsException
二維數(shù)組在創(chuàng)建時可以省略第二維長度(留到后續(xù)指定)红淡,但必須指定第一維長度:
int[][] triangleArray = new int[5][];
triangleArray[0] = new int[5];
triangleArray[1] = new int[4];
triangleArray[2] = new int[3];
triangleArray[3] = new int[4];
triangleArray[4] = new int[5];
如果想打印多維數(shù)組不狮,可以使用嵌套循環(huán)打印,也可以使用Arrays類的deepToString()方法在旱。
零敲碎打
- 一個Java源文件內(nèi)只能有一個public類,且該類名稱必須與文件名相同
- main方法是程序的入口摇零,JVM將從指定類中的main方法開始執(zhí)行。根據(jù)Java語言規(guī)范桶蝎,main方法必須聲明為
public static void main(String[] args)
- 在源代碼中驻仅,字符串常量不能跨行,因此登渣,下面的語句會造成編譯錯誤:
System.out.println("Welcome to the
world of Java!");
為了改正錯誤噪服,可以將該字符串分成幾個單獨的子串,然后再用連接符(+)將它們組合起來:
System.out.println("Welcome to the“ +
”world of Java!");