Mã lệnh đơn giản chạy từ câu lệnh đầu tiên đến câu lệnh cuối cùng mà không đổi hướng thực sự không thể làm được gì nhiều. Để trở nên hữu ích, chương trình của bạn cần đưa ra các quyết định, và có thể hành động khác đi trong những tình huống khác nhau. Giống như bất cứ một ngôn ngữ hữu dụng nào, Java cung cấp cho bạn những công cụ để làm điều đó, dưới dạng các câu lệnh và toán tử. Phần này sẽ đề cập đến các yếu tố sẵn có ấy khi bạn viết mã lệnh Java.
Java cung cấp cho bạn một vài toán tử và câu lệnh điều khiển luồng để cho phép bạn ra quyết định trong mã lệnh của mình. Thông thường, một quyết định lựa chọn trong mã lệnh bắt đầu bằng một biểu thức logic (là biểu thức được đánh giá bằng hai giá trị đúng hoặc sai – true/false). Những biểu thức đó sử dụng các toán tử quan hệ, chúng so sánh một toán hạng hoặc một biểu thức với một với một toán hạng hay biểu thức khác, và các toán tử điều kiện nữa. Dưới đây là danh sách:
Toán tử | Cách sử dụng | Trả về true nếu... |
> | a > b | a lớn hơn b |
>= | a >= b | a lớn hơn hay bằng b |
< | a < b | a nhỏ hơn b |
<= | a <= b | a nhỏ hơn hay bằng b |
== | a == b | a bằng b |
! = | a != b | a không bằng b |
&& | a && b | a và b cả hai đều true, tính b có điều kiện(nếu a là false thì không cần tính b nữa) |
|| | a || b | a hoặc b là true, tính b có điều kiện(nếu a là true thì không cần tính b nữa) |
! | ! a | a là false |
& | a & b | a và b cả hai là true, luôn luôn tính b |
| | a | b | a hoặc b là true, luôn luôn tính b |
^ | a ^ b | a và b là khác nhau (true nếu a là true và b là false,hoặc ngược lại, nhưng không được đồng thời là true hoặc false) |
Giờ ta phải dùng những toán tử đó. Hãy thêm một vài biểu thức logic đơn giản vào phương thức
walk()
của chúng ta:public String walk(int steps) {
if (steps > 100)
return "I can't walk that far at once";
progress = progress + steps;
return "Just took " + steps + " steps.";
}
|
Bây giờ logic hoạt động trong phương thức này sẽ kiểm tra xem số lượng
steps
lớn như thế nào. Nếu quá lớn, phương thức sẽ ngay lập tức trả về và thông báo rằng thế là quá xa. Mỗi phương thức có thể trả về chỉ một lần. Nhưng bạn thấy, có phải có hai giá trị trả về ở đây đúng không? Đúng, nhưng chỉ có một lần trả về được thực thi mà thôi. Điều kiện if
của Java có khuôn dạng như sau:if ( boolean expression ) {
statements to execute if true...
} [else {
statements to execute if false...
}]
|
Cặp ngoặc nhọn không bắt buộc nếu chỉ có một lệnh đơn sau từ khóa
if
hay sau từ khóa else
, đó là lý do vì sao mã lệnh của chúng ta không dùng đến cặp ngoặc này. Bạn không bắt buộc phải có mệnh đề else
, và trong mã lệnh của ta cũng không có. Chúng ta có thể đặt các mã lệnh còn lại của phương thức trong mệnh đề else
nhưng hiệu lực cũng sẽ tương đương và những thứ thêm vào một cách không cần thiết như thế được gọi là gia vị cú pháp vô ích, nó làm giảm tính dễ đọc của mã lệnh.
Tất cả các biến trong ứng dụng Java đều có một phạm vi (scope), hay là các đặc trưng xác định nơi bạn có thể truy cập biến chỉ bằng tên của nó. Nếu biến nằm trong vùng phạm vi, bạn có thể tương tác với nó bằng tên. Nếu biến nằm ngoài vùng phạm vi thì điều này là không thể.
Có nhiều mức phạm vi trong ngôn ngữ Java, được xác định bởi vị trí khai báo của biến ở đâu (Lưu ý: không phải tất cả đều là chính thức, theo như tôi biết, nhưng chúng thường là những cái tên mà người lập trình vẫn dùng).
public class SomeClass {
member variable scope
public void someMethod( parameters ) {
method parameter scope
local variable declaration(s)
local scope
someStatementWithACodeBlock {
block scope
}
}
}
|
Phạm vi của một biến trải rộng cho đến cuối đoạn (hoặc cuối khối) mã lệnh mà nó được khai báo trong đó. Ví dụ, trong phương thức
walk()
, chúng ta tham chiếu đến tham số steps
bằng cái tên đơn giản của nó, vì nó nằm trong phạm vi. Ở ngoài phương thức này, khi nói đến steps
thì trình biên dịch sẽ báo lỗi. Mã lệnh cũng có thể gọi đến các biến đã được khai báo trong phạm vi rộng hơn mã đó. Ví dụ, chúng ta được phép tham chiếu đến biến cá thể progress
bên trong phương thức walk()
.
Chúng ta có thể tạo ra một câu lệnh kiểm tra điều kiện đẹp hơn bằng cách viết lệnh
if
dưới dạng khác:if ( boolean expression ) {
statements to execute if true...
} else if ( boolean expression ) {
statements to execute if false...
} else if ( boolean expression ) {
statements to execute if false...
} else {
default statements to execute...
}
|
Phương thức của chúng ta có thể giống như sau:
if (steps > 100)
return "I can't walk that far at once";
else if (steps > 50)
return "That's almost too far";
else {
progress = progress + steps;
return "Just took " + steps + " steps.";
}
|
Có một dạng viết tắt của lệnh
if
trông hơi xấu, nhưng cùng đạt được mục đích, mặc dù dạng viết tắt này không cho phép có nhiều câu lệnh cả trong phần if
lẫn trong phần else
. Dó là dùng toán tử tam nguyên ?:
. (Toán tử tam nguyên là toán tử có ba toán hạng). Chúng ta có thể viết lại câu lệnh if
đơn giản theo cách sau:return (steps > 100) ? "I can't walk that far at once" : "Just took " + steps + " steps.";
|
Tuy nhiên, câu lệnh này không đạt được mục đích vì khi
steps
nhỏ hơn 100, chúng ta muốn trả về một thông điệp và đồng thời muốn cập nhật biến progress
. Bởi vậy trong trường hợp này, sử dụng toán tử tắt ?:
không phải là một lựa chọn vì chúng ta không thể thực thi nhiều câu lệnh với dạng viết tắt này.
Lệnh
if
chỉ là một trong số các câu lệnh cho phép bạn kiểm tra điều kiện trong mã lệnh. Một câu lệnh khác bạn rất có thể đã gặp là lệnh switch
. Nó đánh giá một biểu thức số nguyên, sau đó thực thi một hay nhiều câu lệnh dựa trên giá trị của biểu thức này. Cú pháp của lệnh như sau:switch ( integer expression ) {
case 1:
statement(s)
[break;]
case 2:
statement(s)
[break;]
case n:
statement(s)
[break;]
[default:
statement(s)
break;]
}
|
JRE đánh giá biểu thức số nguyên, chọn ra trường hợp áp dụng, sau đó thực thi câu lệnh của trường hợp này. Câu lệnh cuối cùng của mỗi trường hợp ngoại trừ trường hợp cuối là
break;
. Nó là “lệnh thoát” của switch
, và điều khiển sẽ tiếp tục xử lý dòng tiếp theo trong mã lệnh sau câu lệnh switch
. Về mặt kỹ thuật, không cần có lệnh break;
. Câu lệnh break
cuối cùng lại càng đặc biệt không cần thiết vì dù gì thì điều khiển cũng tự thoát khỏi câu lệnh. Nhưng cách làm tốt là cứ thêm chúng vào. Nếu bạn không thêm lệnh break;
ở cuối mỗi trường hợp, việc thực thi chương trình sẽ rơi vào trường hợp kế tiếp và tiếp tục chạy, cho đến khi gặp một câu lệnh break;
hoặc đến khi kết thúc câu lệnh switch
. Trường hợp default
sẽ được thực hiện nếu giá trị số nguyên không kích hoạt bất cứ trường hợp nào khác. Điều này không bắt buộc.
Về bản chất, câu lệnh
switch
thực sự là câu lệnh if-else if
với điều kiện của lệnh if
là số nguyên; nếu điều kiện của bạn dựa trên một giá trị số nguyên đơn lẻ, bạn có thể dùng hoặc là lệnh switch hoặc là lệnh if-else. Vậy chúng ta có thể viết lại điều kiệnif
của chúng ta trong phương thức walk
dưới dạng câu lệnh switch
được không? Câu trả lời là không vì chúng ta đã kiểm tra một biểu thức logic ( steps > 100
). Câu lệnh switch
không cho phép kiểm tra như thế.
Đây là một ví dụ thông thường về việc sử dụng câu lệnh
switch
(nó là một ví dụ khá cổ điển):int month = 3;
switch (month) {
case 1: System.out.println("January"); break;
case 2: System.out.println("February"); break;
case 3: System.out.println("March"); break;
case 4: System.out.println("April"); break;
case 5: System.out.println("May"); break;
case 6: System.out.println("June"); break;
case 7: System.out.println("July"); break;
case 8: System.out.println("August"); break;
case 9: System.out.println("September"); break;
case 10: System.out.println("October"); break;
case 11: System.out.println("November"); break;
case 12: System.out.println("December"); break;
default: System.out.println("That's not a valid month number."); break;
}
|
month
là một biến nguyên biểu thị số hiệu của tháng. Vì là số nguyên nên câu lệnh switch
ở đây là hợp lệ. Với mỗi trường hợp hợp lệ, chúng ta in ra tên tháng, sau đó thoát khỏi câu lệnh. Trường hợp mặc định quản lý các số nằm ngoài phạm vi hợp lệ của các tháng.
Cuối cùng, đây là một ví dụ về việc dùng nhiều trường hợp thông nhau có thể sẽ là một mẹo nhỏ thú vị:
int month = 3;
switch (month) {
case 2:
case 3:
case 9: System.out.println("My family has someone with a birthday in this month."); break;
|-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error: The previous line is longer than the max of 90 characters ---------|
case 1:
case 4:
case 5:
case 6:
case 7:
case 8:
case 10:
case 11:
case 12: System.out.println("Nobody in my family has a birthday in this month."); break;
default: System.out.println("That's not a valid month number."); break;
}
|
Ở đây ta thấy trường hợp 2, 3 và 9 được xử lý giống nhau; các trường hợp còn lại có một kiểu xử lý khác. Lưu ý rằng các trường hợp này không phải xếp liền theo thứ tự và có nhiều trường hợp thông nhau là những gì chúng ta cần trong tình huống này.
Đến giờ, chúng ta đã học được nhiều thứ, nhưng vẫn còn những hạn chế. Thỉnh thoảng chúng ta muốn mã lệnh thi hành đi thi hành lại cùng một việc cho đến khi công việc hoàn tất. Ví dụ, giả sử ta muốn đối tượng
Adult
của chúng ta nói hơn một lần câu “hello”. Điều này khá dễ thực hiện trong mã lệnh Java (mặc dù không dễ thực hiện trong các ngôn ngữ kịch bản lệnh như Groovy chẳng hạn). Java cung cấp cho bạn các cách sau để lặp đi lặp lại mã lệnh, hoặc thực hiện mã lệnh hơn một lần:- câu lệnh
for
- câu lệnh
do
- câu lệnh
while
Chúng thường được gọi chung là các vòng lặp (loops) (ví dụ, vòng lặp for), vì chúng lặp đi lặp lại cả khối mã lệnh cho đến khi bạn ra lệnh cho chúng dừng lại. Trong các phần tiếp sau, chúng ta sẽ nói ngắn gọn về từng lệnh một và dùng chúng trong phương thức
speak()
để trò chuyện chút ít.
Cấu trúc lặp cơ bản nhất trong ngôn ngữ Java là câu lệnh
for
, câu lệnh này cho phép bạn lặp từng bước trên một phạm vi giá trị cho phép xác định số lần thực thi vòng lặp. Cú pháp thường sử dụng nhất của vòng lặp for như sau:for ( initialization; termination; increment ) {
statement(s)
}
|
Biểu thức khởi tạo (initialization) xác định vòng lặp bắt đầu từ đâu. Biểu thức dừng (termination) xác định vòng lặp kết thúc ở đâu.Biểu thức tăng (increment) xác định biến khởi tạo sẽ tăng bao nhiêu mỗi lần đi qua vòng lặp. Mỗi lần lặp, vòng lặp sẽ thực hiện các câu lệnh trong khối lệnh, là tập hợp các câu lệnh nằm giữa dấu ngoặc nhọn (hãy nhớ rằng bất kỳ khối nào trong mã lệnh Java cũng được đặt giữa hai dấu ngoặc nhọn, chứ không phải chỉ mã lệnh của vòng lặp
for
).
Cú pháp và khả năng của vòng lặp
for
có khác trong Java phiên bản 5.0, do vậy hãy đọc bài viết của John Zukowski về các đặc tính mới, thú vị trong ấn bản mới ra gần đây của ngôn ngữ này. (xem Các tài nguyên).
Ta hãy biến đổi phương thức
speak()
sao cho nó nói từ “hello” ba lần, dùng vòng lặp for. Khi làm việc này, chúng ta sẽ tìm hiểu về một lớp có sẵn của Java, làm việc lắp ghép các chuỗi một cách 'ngon lành':public String speak() {
StringBuffer speech = new StringBuffer();
for (int i = 0; i < 3; i++) {
speech.append("hello");
}
return speech.toString();
}
|
Lớp
StringBuffer
trong gói java.lang
cho phép bạn thao tác các chuỗi dễ dàng và rất tuyệt vời trong việc nối các chuỗi lại với nhau (giống như ta móc chúng lại với nhau). Đơn giản là chúng ta khởi tạo một chuỗi, sau đó gọi phương thức append()
mỗi lần muốn thêm một điều gì đó vào lời nói của từng Adult
. Vòng lặp for
là nơi mọi việc thực sự diễn ra. Trong cặp ngoặc đơn của vòng lặp, chúng ta đã khai báo một biến nguyên i
để làm số đếm cho vòng lặp (các ký tự i, j và k thường được dùng làm biến đếm vòng lặp, nhưng bạn có thể đặt bất kỳ tên nào mà bạn muốn cho biến này). Biểu thức tiếp theo cho biết chúng ta sẽ tiếp tục lặp cho đến khi biến này đạt đến một giá trị nhỏ hơn ba. Biểu thức sau cho biết chúng ta sẽ tăng biến đếm lên một sau mỗi lần lặp (hãy nhớ toán tử ++
). Mỗi lần đi qua vòng lặp, chúng ta sẽ gọi phương thức append()
của speech
và dán một từ “hello” khác vào cuối.
Bây giờ, thay phương thức
speak()
cũ bằng phương thức speak()
mới, loại bỏ mọi lệnh println
trong main()
và thêm một lệnh để gọi phương thức speak()
của Adult
. Khi bạn thực hiện, lớp có thể giống như sau:package intro.core;
public class Adult {
protected int age = 25;
protected String firstname = "firstname";
protected String lastname = "lastname";
protected String race = "inuit";
protected String gender = "male";
protected int progress = 0;
public static void main(String[] args) {
Adult myAdult = new Adult();
System.out.println(myAdult.speak());
}
public int getAge() {
return age;
}
public void setAge(int anAge) {
age = anAge;
}
public String getName() {
return firstname.concat(" ").concat(lastname);
}
public String speak() {
StringBuffer speech = new StringBuffer();
for (int i = 0; i < 3; i++) {
speech.append("hello");
}
return speech.toString();
}
public String walk(int steps) {
if (steps > 100)
return "I can't walk that far at once";
else if (steps > 50)
return "That's almost too far";
else {
progress = progress + steps;
return "Just took " + steps + " steps.";
}
}
}
|
Khi bạn chạy đoạn mã lệnh này, bạn sẽ nhận được kết quả là dòng
hellohellohello
trên màn hình. Nhưng dùng vòng lặp for
chỉ là một cách để làm việc này. Java còn cho bạn hai cấu trúc thay thế khác mà bạn sẽ thấy tiếp theo đây.
Đầu tiên hãy thử vòng lặp
while
. Phiên bản sau đây của phương thức speak()
cho ra cùng một kết quả như cách làm mà bạn thấy ở phần trên:public String speak() {
StringBuffer speech = new StringBuffer();
int i = 0;
while (i < 3) {
speech.append("hello");
i++;
}
return speech.toString();
}
|
Cú pháp cơ bản của vòng lặp
while
như sau:while ( boolean expression ) {
statement(s)
}
|
Vòng lặp
while
thực hiện mã lệnh trong khối cho đến khi biểu thức của nó trả lại giá trị là false
. Vậy bạn điều khiển vòng lặp như thế nào? Bạn phải đảm bảo là biểu thức sẽ trở thành false tại thời điểm nào đó, nếu không, bạn sẽ có một vòng lặp vô hạn. Trong trường hợp của chúng ta, ta khai báo một biến địa phương là i ở bên ngoài vòng lặp, khởi tạo cho nó giá trị là 0, sau đó kiểm tra giá trị của nó trong biểu thức lặp. Mỗi lần đi qua vòng lặp, chúng ta lại tăng i lên. Khi nó không còn nhỏ hơn 3 nữa, vòng lặp sẽ kết thúc và chúng ta sẽ trả lại xâu ký tự lưu trong bộ đệm.
Ở đây ta thấy vòng
for
thuận tiện hơn. Khi dùng vòng for
, chúng ta khai báo và khởi tạo biến điều khiển, kiểm tra giá trị của nó và tăng giá trị của nó chỉ bằng một dòng mã lệnh. Dùng vòng while
đòi hỏi nhiều việc hơn. Nếu chúng ta quên tăng biến đếm, chúng ta sẽ có một vòng lặp vô hạn. Nếu ta không khởi tạo biến đếm, trình biên dịch sẽ nhắc nhở. Nhưng vòng while
lại rất tiện lợi nếu bạn phải kiểm tra một biểu thức logic phức tạp (đóng hộp tất cả vào vòng lặp for
thú vị ấy sẽ làm cho nó rất khó đọc).
Bây giờ ta đã thấy vòng lặp
for
và while
, nhưng phần tiếp theo sẽ minh họa cho ta thấy còn một cách thứ ba nữa.
Đoạn mã lệnh sau đây sẽ thực thi chính xác những điều mà ta thấy ở hai vòng lặp trên:
public String speak() {
StringBuffer speech = new StringBuffer();
int i = 0;
do {
speech.append("hello");
i++;
} while (i < 3) ;
return speech.toString();
}
|
Cú pháp cơ bản của vòng lặp
do
như sau:do {
statement(s)
} while ( boolean expression ) ;
|
Vòng lặp
do
gần như giống hệt vòng lặp while
, ngoại trừ việc nó kiểm tra biểu thức logic sau khi thực thi khối lệnh lặp. Với vòng lặp while
, chuyện gì sẽ xảy ra nếu biểu thức cho giá trị false
ngay lần đầu tiên kiểm tra? Vòng lặp sẽ không thực hiện dù chỉ một lần. Còn với vòng lặp do
, bạn sẽ được đảm bảo là vòng lặp sẽ thực hiện ít nhất 1 lần. Sự khác biệt này sẽ có ích trong nhiều trường hợp.
Trước khi tạm biệt các vòng lặp, hãy xem lại hai câu lệnh rẽ nhánh. Chúng ta đã thấy lệnh
break
khi ta nói đến câu lệnh switch
. Nó cũng có hiệu quả tương tự trong vòng lặp: nó dừng vòng lặp. Mặt khác, lệnh continue
giúp dùng ngay lần lặp hiện tại và chuyển tới lần lặp tiếp theo. Đây là một ví dụ thường thấy:for (int i = 0; i < 3; i++) {
if (i < 2) {
System.out.println("Haven't hit 2 yet...");
continue;
}
if (i == 2) {
System.out.println("Hit 2...");
break;
}
}
|
Nếu bạn đưa đoạn mã này vào trong phương thức
main()
và chạy, bạn sẽ nhận được kết quả như sau:Haven't hit 2 yet...
Haven't hit 2 yet...
Hit 2...
|
Hai lần đầu đi qua vòng lặp,
i
đều nhỏ hơn 2, do vậy chúng ta in ra dòng chữ “Haven't hit 2 yet...”, sau đó thực hiện lệnhcontinue
, lệnh này chuyển luôn đến lần lặp tiếp theo. Khi i
bằng 2, khối mã lệnh trong phần lệnh if
đầu tiên không được thi hành. Chúng ta nhảy đến lệnh if
thứ hai, in ra dòng chữ "Hit 2...", sau đó lệnh break
thoát khỏi vòng lặp.
Trong phần tiếp theo, chúng ta sẽ tăng thêm sự phong phú của các hành vi có thể bổ sung thêm thông qua việc trình bày về việc xử lý các bộ sưu tập (Collections).
lập trình java-trang 9
lập trình java-trang 10
lập trình java-trang 9
lập trình java-trang 10
0 nhận xét:
Post a Comment