語句同樣是Java重要的基礎語言要素之一,那么在Java中語句是以什么形式體現的呢?通常分為:
- 簡單語句:就如同語文中以句號“。”結尾的一個句子就是一句語句一樣,Java中以分號“;”結尾的一段代碼就是最基本的一條Java語句。
- 塊(復合)語句:指以一對花括號"{ }"包含起來的一系列程序語句的集合,所以又被稱為復合語句。
提到塊語句,我們就不得不提及與之緊密相關的一個名詞:代碼塊。
代碼塊實際上也可以理解為作用域,之所以這樣講,是因為我們已經說過了代碼塊是以花括號“{ }”包含起來的一系列語句。
而塊定義了變量的使用范圍,各個塊之間可以進行嵌套,而在塊中聲明的變量,只在當前塊當中有效,在塊以外將無法使用。
所以說,在使用代碼塊的時候,需要十分注意的兩點就是:
- 注意變量的作用范圍,不要在無效范圍中使用該變量,否則程序將編譯失敗。
- 不要在嵌套的兩個塊中,聲明使用相同標示符的變量,否則也將導致程序編譯失敗。
那么,首先我們來看第一個注意點:

在這段代碼中,值得我們注意的是:
- **一個完整的Java程序(類)實際上正是由一個個嵌套的代碼塊組合起來的**。就像在類聲明后用花括號包含起來的代碼塊被稱為類代碼塊,方法聲明后包含的代碼塊被稱為方法代碼塊,嵌套在方法內的代碼塊被稱為局部代碼塊等等一樣。
- **嵌套在更內部層次的代碼塊可以使用嵌套外部的代碼塊中的內容,但位于嵌套更外部層次的代碼塊不能使用更內部層次的代碼塊中的內容。**所以在上面的例子中我們看到,方法代碼塊中可以使用類代碼塊中聲明的變量;局部代碼塊中,在類代碼塊和方法代碼快中聲明的變量都能夠被訪問;但最后想要在方法代碼塊中訪問局部代碼塊中聲明的變量,程序就編譯失敗了。**這一切現象出現的原因,正是因為:在塊中聲明的變量只在當前塊中有效。**
- **合理的使用代碼塊,可以在一定程度上節約內存開銷。**這是因為之所以說塊中聲明的變量只在當前塊中有效,深入的講,實際就是因為代碼塊限定了其生命周期,也就是說當虛擬機執行到該代碼塊,當中聲明的變量才會被加載到內存之中,而隨著該代碼塊的代碼都執行完畢,當中的變量就會在內存中被釋放,所以自然在塊以外就無法再訪問到了。****
接著,我們來看第二個注意點:

注意以上代碼截圖中,用紅色方框標記的兩行代碼。
我們寫這段代碼想要驗證的是代碼塊的特性之一:不要在嵌套的兩個代碼塊中聲明相同命名的變量。
那么,第二個紅框標注的代碼恰恰印證了這一點,在方法代碼塊中聲明了名為“method_block_var”的變量之后,如果再在其嵌套的局部代碼塊中聲明,就會導致編譯出錯。
但讓人在意的是,我們在類代碼塊中聲明了一個“class_block_var”的變量,為何之后我們在其嵌套的方法代碼塊中,仍然可以聲明相同命名的變量呢?
這實際上涉及到Java的內存機制,首先我們需要知道的就是:Java中聲明在類代碼塊中的變量被稱為該類的成員變量,而聲明在方法或局部代碼塊中的變量被稱為局部變量。
之所以造成這樣的現象,究其根本是因為虛擬機內部的內存結構對于成員變量和局部變量的存儲位置是不同的:
類的成員變量會隨著類的對象一起,被存儲在內存當中的堆內存當中;而局部變量則會隨著方法的加載,而被存儲到棧內存當中(方法的壓棧)。
到了這里就不難理解了:
1.不同的兩個班級:一班(堆內存)和二班(棧內存)中,都有一個名為“ 小明”的同學(變量)。這樣的情況是沒有任何問題的,因為你在調用時,可以通過“一班的小明”和“二班的小明”來正確的調用到目標學生。Java中也是這樣的,在對成員變量進行調用時,實際上是隱式的調用了當前類對象關鍵字this。也就是說對成員變量的調用實際上是以:this.var的形式進行調用的,這就很好的與局部變量調用區分開了。
2.但同一個班級中(都位于棧內存)有兩個相同名字的學生 ,那么再想要正確的調用目標學生就很難了,這會產生“調用的不確定性”。所以自然的,Java作為一門嚴謹的具有高度健壯性的語言,自然不會允許這樣的“危險因素”存在。
**
**
**流程控制語句的使用**
話到這里,就來到了一個重要的部分:Java的程序流程控制語句的使用。
之所以使用流程控制語句,是因為一個程序的運行都是有序的,通常都是按照代碼的書寫順序從上到下,從左到右進行執行。這一過程被稱為順序執行。
但實際開發中,我們通常都要根據實際需求,對程序的運行方式做一些目的性的改變,例如加一些條件判斷等等。
于是,這個時候就必須用到流程控制語句,來進行程序流程的控制工作了。
Java中,主要的流程控制語句分為三種:選擇/條件語句,循環語句,跳轉語句。
**
**
**一、選擇/條件語句**
顧名思義,就是指一段程序根據條件判斷之后,根據判斷結果再選擇不同的處理方式的語句結構。
而必須銘記的是:條件語句的判斷條件必須滿足是boolean類型的數據。即:
條件只可以是一個boolean類型的值;是一個boolean類型的變量;或是一個返回boolean類型值的表達式。
**1.1、if條件語句.**
最簡單的條件語句,作為條件分支語句,可以控制程序選擇不同的處理方式執行。有三種表現形式:
第一種表現形式:if。
通常用于只有當滿足某個條件,才具備程序繼續執行的資格的情況。例如:判斷一個人的年齡,只有判斷結果為成年,才能繼續執行相關代碼:
~~~
private void if_Demo_1(int age) {
if (age >= 18) {
System.out.println("已成年,可以執行相關代碼..");
//上網..
//飲酒..
}
}
~~~
第二種表現形式:if - else。
通常用于條件判斷可能存在兩種結果的情況.例如,判斷一個人的性別,性別非男即女:
~~~
private void if_Demo_2(String gender) {
if (gender.equals("male")) {
System.out.println("男性");
} else {
System.out.println("女性");
}
}
~~~
第三種表現形式:if - else if - else。
通常用于當條件判斷可能存在兩種以上結果的情況。例如,判斷兩個數a與b的大小,則可能存在a大于b,b大于a或二者相等的三種情況:
~~~
private void if_Demo_2(int a, int b) {
if (a > b) {
System.out.println(a + "大于" + b);
} else if (a < b) {
System.out.println(b + "大于" + a);
} else {
System.out.println(a + "等于" + b);
}
}
~~~
最后順帶一提的就是,某些情況下會存在:僅僅通過一次條件判斷,還無法選擇正確的處理方式的情況。這時就可以通過對if語句嵌套,完成多次判斷:
~~~
/*
* 一家俱樂部,只針對年滿18歲的女性營業
*/
private void if_Demo_4(String gender, int age) {
if (gender.equals("male")) {
if (age >= 18) {
System.out.println("歡迎觀臨.");
} else {
System.out.println("對不起,您未滿18歲!");
}
} else {
System.out.println("對不起,我們只針對女性營業!");
}
}
~~~
**1.2、switch條件/選擇語句**
我們注意到在if語句的使用中,如果當條件判斷存在多種結果的時候,則必須使用“if - else if - else”的方式來處理。
那自然我們可以想象如果當一個條件存在大量的可能結果時,我們可能就必須書寫大量的else if語句,這樣做可能會比較麻煩。
針對于這樣的情況,Java提供了另一種相對簡單一些的形式,就是switch條件語句。對于switch語句,值得注意的是:
其接受的條件只能是一個整型數據或枚舉常量,只是在JDK1.7之后又新支持了String類型。
而同時我們知道Java中支持數據類型轉換,而byte,short,char都可以被隱式的自動轉換為int。
所以通常來說:switch語句所能接受的條件只能是byte,short,int,char或枚舉類型的數據。
正是因為如此,所以switch語句相對于if語句而言,本身存在一定的局限性。
通常來說,一個switch語句的定義格式為:
~~~
switch (key) {
case value:
break;
default:
break;
}
~~~
舉例而言,假設我們通過用戶輸入的一個整數,來查詢對應的星期數:
~~~
private void switch_demo(int num) {
switch (num) {
case 1:
System.out.println("星期一");
break;
case 2:
System.out.println("星期二");
break;
case 3:
System.out.println("星期三");
break;
case 4:
System.out.println("星期四");
break;
case 5:
System.out.println("星期五");
break;
case 6:
System.out.println("星期六");
break;
case 7:
System.out.println("星期日");
break;
default:
System.out.println("沒有對應的星期數");
break;
}
}
~~~
swtich語句的執行過程是這樣的,首先計算條件表達式的值,然后根據值分別對每個case進行匹配工作。
假如找到對應的匹配,則執行該case值下的程序語句;如果沒有匹配的case值,則執行default下的程序語句。
在執行完case的語句塊后,應當使用跳轉語句break語句跳出該switch語句。
因為如果沒有添加break語句,程序在執行完匹配的case值下的程序語句后,
并不會停止,而是將會連續執行下一個case值下的代碼,直到碰到break語句為止。
**多重if和switch的區別**
我們已經知道在某些情況下,多重if和switch是可以完成相同的目的的。而它們最大的區別就在于:
switch語句局限性更大,這是因為我們說過了:switch語句只能對類型為byte,short,int,long或枚舉的數據的具體值進行判斷。
但if既可以對具體的值進行判斷;也可以進行區間判斷;同時還可以對返回值類型為boolean類型的表達式進行判斷,如:
~~~
public void ifTest(int a, char c,String s) {
//對具體的值進行判斷
if(a == 5);
if(c == 'a');
if(s.equals("s"));
//對區間進行判斷
if(a>5&&a<=10);
//對返回值為boolean類型的表達式進行判斷
if(a>=c);
}
~~~
而網上很多人說,switch語句的效率相對高于if語句。這是因為:switch語句會將所有可能情況的代碼語句一次性都加載進內存,所以在執行時效率相對較高。
但因為其本身的局限性,所以在實際開發中,還是因該根據實際需求選擇最合適的做法。
**二、循環語句**
顧名思義,循環語句也就是指用于控制同一段程序反復多次運行的語句。Java中循環語句有三種,分別為:while、do-while以及for循環。
可以說,三種循環語句之間的區別實際不大,但同時也可以說都有本質的區別。下面我們分別來看一下三種循環的原理和使用。
**2.1、while循環語句**
~~~
/*
* while循環語句的定義格式為:
* while(條件){
* //循環內容..
* }
*/
private void while_demo(int a){
while(a < 20){
System.out.println(++a);
}
}
~~~
與if條件語句相同,while語句也會接受一個boolean類型的值作為條件。
當該條件判斷為true時,則會循環執行循環體的內容;當執行到條件判斷結果為false時,就會結束循環。
**2.2、do-while循環語句**
~~~
/*
* do-while循環語句的定義格式為:
* do {
//循環體
} while (condition);
*/
private void do_while_demo(int a){
do {
System.out.println("執行一次循環:"+(++a));
} while (a<20);
}
~~~
do-while循環與while循環最大的不同就是:無論循環條件的判斷結果是否為true,都會至少執行一次循環體中的內容。
之所以Java會單獨提供do-while這種循環方式,也正是因為:當使用while循環的時候,如果首次判斷循環條件的結果就為假的話,那么該循環就會直接被跳過,根本不會執行。而事實上,我們很多時候會希望循環體至少執行一次。
**2.3、for循環語句**
~~~
/*
* for循環的定義格式為:
* for(初始化表達式;循環條件表達式;迭代運算)
* {
* 執行語句;(循環體)
* }
*/
private void for_demo(){
for (int i = 0; i < 20; i++) {
System.out.println(++i);
}
}
~~~
for循環的執行過程為:
1.執行循環的初始化,通過它設置循環的控制變量值
2.判斷循環條件:如果為真,則執行循環體內容;如果為假,則退出循環;
3.執行迭代運算。迭代運算通常是一個表達式,用于改變循環控制變量的值。
4.再次執行循環條件判斷,然后反復第2-3步的步驟,直到循環條件判斷為假時,則退出循環。
需要注意的是:for循環的初始化表達式,只會在循環第一次開始時執行一次;
而迭代運算表達式則會在每一次循環體內容執行完畢后,緊接著執行一次。
可以通過一道網上流傳的華為的Java面試題,來更形象的了解for循環的執行特點:
~~~
/*
What is the result?
A. ABDCBDCB
B. ABCDABCD
C. Compilation fails.
D. An exception is thrown at runtime.
*/
public class Demo {
static boolean foo(char c) {
System.out.print(c);
return true;
}
public static void main(String[] args) {
int i = 0;
//ABDCBDCB
for (foo('A'); foo('B') && (i < 2); foo('C')) {
i++;
foo('D');
}
}
}
~~~
最終執行的結果為:ABDCBDCB,我們來逐步分解該輸出結果形成的原因:
1.for循環第一次開始執行,首先執行循環初始化表達式,于是foo('A')被執行,輸出A。此時輸出結果為:A
2.緊接著開始執行循環條件判斷,于是foo('B')被執行,輸出B;接著判斷i(0)<2;循環條件判斷結果為真。此時輸出結果為:AB
3.由于該次判斷結果為真,于是開始執行循環體。于是,i自增運算,值變為1;foo('D')被執行,輸出D。此時輸出結果為:ABD
4.一次循環體內容執行完畢,緊接著開始執行迭代運算表達式:foo('C'),于是輸出C。此時輸出結果為:ABDC
5.再次開始新一次的循環條件判斷,于是foo('B')被執行,輸出B;接著判斷i(1)<2;循環條件判斷結果為真。此時輸出結果為:ABDCB
6.再次開始執行循環體。于是i繼續自增運算,值變為2;foo('D')被執行,輸出D。此時輸出結果為:ABDCBD
7.循環體內容又一次執行完畢,同樣緊接著開始執行迭代運算表達式:foo('C'),于是再次輸出C。此時輸出結果為:ABDCBDC
8.進行新一輪的循環條件判斷。于是foo('B')被執行,又一次輸出B;接著判斷i(2)<2,此次循環條件判斷結果為假,于是循環到此退出。
所以,最終該程序的運行結果為:ABDCBDCB
**while循環與for循環的異同**
while循環與for循環之間實際上是可以相互替換的。以常見的數的累加的問題來說,以while循環和for循環分別的實現形式為:
~~~
/*
* 求1到100之間的數累加的和?
*/
public class Demo {
private static int for_demo() {
int sum = 0;
for (int i = 1; i <= 100; i++) {
sum += i;
}
return sum;
}
private static int while_demo() {
int sum = 0;
int i = 0;
while (i <= 100) {
sum = sum + (i++);
}
return sum;
}
public static void main(String[] args) {
System.out.println("通過for循環完成累加的值為:" + for_demo());
System.out.println("通過while循環完成累加的值為:" + while_demo());
}
}
~~~
而while和for之間唯一的小差就在于:循環控制變量的作用域。這實際上正是涉及到在這篇博客中提到的代碼塊的相關知識。從上面的用例代碼中,我們看到:
方法“for_demo”中,用于控制for循環的循環控制變量“i”,被聲明在for循環語句內。所以這里的變量“i”實際上,是被聲明在for循環語句塊當中的局部變量,所以隨著for循環語句塊的運行結束,該變量就會從內存中釋放,走到生命周期的盡頭。
反觀方法“while_demo”中,用于控制while循環的循環控制變量"i"則只能被聲明在屬于"while_demo"的方法代碼塊中,而不屬于循環本身。也就是說,就算當while循環運行結束,該循環控制變量依然有效,仍然可以被訪問,因為它實際是屬于“while_demo”所聲明的代碼塊中。
這也正是我在這個專欄系列里,第一篇文章[《第一個專欄《重走J2SE之路》,你是否和我有一樣的困擾? 》](http://blog.csdn.net/ghost_programmer/article/details/42491083)中提到的:
為什么查看一些Java的源碼時,發現老外很多時候選擇使用for循環的原因,也正是因為for循環相對于while循環,可以在很小程度上減少內存的開銷,
**三、跳轉語句**
跳轉語句是指打破程序的正常運行,跳轉到其他部分的語句。Java提供了三種跳轉語句,分別為:break、continue以及return。
**3.1、break語句**
break語句的使用方式主要三種:跳出switch條件語句、跳出循環以及通過代碼塊的標示符跳出代碼塊。我們通過一段代碼分別看一下它們具體的應用:
~~~
void break_demo(int a) {
// 跳出switch條件語句
switch (a) {
case 1:
System.out.println();
break;
default:
break;
}
// 跳出循環
while (true) {
if (++a > 50) {
break;
}
}
// 跳出代碼塊
my_block_1: {
my_block_2: {
a++;
if (a > 5) {
break my_block_1;
}
}
}
}
~~~
值得注意的是:在使用break跳出循環時,只會跳出其所在的循環,而其外部的循環并不會跳出,還會繼續運行。
**3.2、continue語句**
break語句可以用于跳出其所在循環。但是有時我們需要跳出一次循環剩余的循環部分,但同時還要繼續下一次循環,這時就用到了continue語句。
~~~
void continue_demo(){
for (int i = 1; i <= 30; i++) {
System.out.print(i+"\t");
if(i%5!=0)
continue;
System.out.println("*");
}
}
~~~
這段代碼運行的輸出結果為:

這正是continue語句起到的作用,每執行一次循環體的內容。
首先會輸出“i”當前的值及一個制表符,然后會判斷當前“i”是否是5的倍數。
如果是不是5的倍數,則會通過continue語句結束該次剩余的部分,所以在其之后的輸出語句便不會再被執行。
而如果是5的倍數的話,才會執行之后的輸出語句,輸出一個“*”號,并換行。
由此,最終才出現了上面我們看到的輸出效果。
所以,總的來說break與continue的區別就在于:break語句用于退出整個循環;而continue語句則是用于結束該次循環的剩余循環部分,但繼續新一次的循環。
**
**
**3.3、return語句**
簡單的來說,如果說break用于跳出循環的話,而return語句則是用于結束整個方法并返回。
return語句可以說是實際開發中最常用的跳轉語句了,因為任何方法都需要return語句來控制方法的結束并返回對應類型的值。
~~~
void return_demo_1() {
/*
* 實際上void返回類型的值,也使用了return。 只不過在以void作為返回類型的方法中,return是隱式的存在的。
*/
}
int return_demo_2() {
/*
* 通過return
*/
for (int i = 0; i < 5; i++) {
i++;
for (int j = 0; j < 20; j++) {
if (j == 3) {
/*
* 這里如果使用break,雖然內部循環會被退出,但外部循環仍然會繼續執行
* 而使用return則意味結束整個方法,并返回值“5”,
* 這樣做代表這之后的代表將永遠沒有機會再運行。
*/
return 5;
}
}
// 該語句永遠不會被執行到。
System.out.println("外部循環執行一次..");
}
return 0;
}
~~~
到了這里,Java中程序語句的使用,我們已經有了一個不錯的了解了。最后,就通過一個實際應用的小例子,輸出九九乘法表作為結束吧:
~~~
package com.tsr.j2seoverstudy.base;
public class Print99 {
public static void main(String[] args) {
System.out.println("*****************九九乘法表****************");
for (int i = 1; i <= 9; i++) {
System.out.print("\t"+i);
}
System.out.println();
for (int i = 1; i <= 9; i++) {
System.out.print(i+"\t");
for (int j = 1; j <= i; j++) {
System.out.print(i*j+"\t");
}
System.out.println();
}
}
}
~~~
運行程序,查看其輸出結果:

- 前言
- 第一個專欄《重走J2SE之路》,你是否和我有一樣的困擾?
- 磨刀不誤砍材工 - 環境搭建(為什么要配置環境變量)
- 磨刀不誤砍材工 - Java的基礎語言要素(定義良好的標示符)
- 磨刀不誤砍材工 - Java的基礎語言要素(關鍵字)
- 磨刀不誤砍材工 - Java的基礎語言要素(注釋-生成你自己的API說明文檔)
- 磨刀不誤砍材工 - Java的基礎語言要素(從變量/常量切入,看8種基本數據類型)
- 磨刀不誤砍材工 - Java的基礎語言要素(運算符和表達式的應用)
- 磨刀不誤砍材工 - Java的基礎語言要素(語句-深入理解)
- 磨刀不誤砍材工 - Java的基礎語言要素(數組)
- 換一個視角看事務 - 用&quot;Java語言&quot;寫&quot;作文&quot;
- 牛刀小試 - 淺析Java的繼承與動態綁定
- 牛刀小試 - 詳解Java中的接口與內部類的使用
- 牛刀小試 - 趣談Java中的異常處理
- 牛刀小試 - 詳解Java多線程
- 牛刀小試 - 淺析Java集合框架的使用
- 牛刀小試 - Java泛型程序設計
- 牛刀小試 - 詳細總結Java-IO流的使用