Các câu lệnh quyết định
Khai báo các biến luận lý
Mệnh đề (hay biểu thức) luận lý là các mệnh đề chỉ nhận giá trị đúng (true) hay sai (false).
Java cung cấp kiểu dữ liệu boolean là kiểu dữ liệu luận lý. Một biến kiểu luận lý chỉ chứa một trong hai giá trị là true hay false.
Các toán tử luận lý
Trả về giá trị true hay false từ việc kết hợp nhiều biểu thức. Một số toán tử
Toán tử | Chức năng |
& | Trả về true nếu tất cả các biểu thức đều trả về true |
| | Trả về true nếu ít nhất một biểu thức trả về true |
! | Trả về true nếu biểu thức là false và ngược lại |
&& | Tương tự & nhưng sẽ không kiểm tra các biểu thức còn lại nếu biểu thức đầu tiên quyết định kết quả trả về. |
|| | Tương tự | nhưng sẽ không kiểm tra các biểu thức còn lại nếu biểu thức đầu tiên quyết định kết quả trả về. |
Ví dụ:
int num1 = 3; int num2 = 7; num1 == 3 & num2 == 7 // true num1 == 2 & num2 == 7 // false num1 == 3 | num2 == 11 // true !(num1 == 5) // true num1 == 2 && num2 == 7 //trả về false vì num1 khác 2 và không //cần kiểm tra biểu thức num2 = 7
Bên cạnh các toán tử luận lý còn có toán tử quan hệ hay bằng >, <, >=, <=, ==, ! dùng để tạo các biểu thức luận lý và độ ưu tiên của các toán tử. Có thể tham khảo lại chương IV.
Các lệnh điều kiện (conditional statement): if và switch
Khi viết code, chúng ta hay gặp những tình huống phải đưa ra những hành động khác nhau trong những điều kiện khác nhau. Để làm điều này, chúng ta sử dụng các lệnh điều kiện (conditional statements).
Lệnh if
Cú pháp:
if (logical expression) { statement }
Sơ đồ khối
Nếu biểu thức logical expression nhận giá trị true thì thực hiện lệnh (hay khối lệnh) statement, ngược lại không làm gì.
Ví dụ:
if (age < 18) { message = "You are under 18 years of age!"; }
Lệnh if…else
Cú pháp:
if (logical expression) { statement1 } else { statement2 }
Sơ đồ khối
Nếu biểu thức logical expression nhận giá trị true thì thực hiện lệnh (hay khối lệnh) statement1, ngược lại thực hiện lệnh (hay khối lệnh) statement2.
Ví dụ:
if (age < 18) { message = "You are under 18 years of age!"; } else { message = "Welcome to our website!"; }
Lệnh if…else if…else
Cú pháp:
if (logical expression 1) { statement1 } else if (logical expression 2) { statement2 } else { statement3 }
Nếu biểu thức logical expression 1 nhận giá trị true thì thực hiện lệnh (hay khối lệnh) statement1, ngược lại (biểu thức logical expression 1 nhận giá trị false) nếu biểu thức logical expression 2 nhận giá trị true thực hiện lệnh (hay khối lệnh) statement2 và nếu biểu thức logical expression 2 nhận giá trị false thì thực hiện lệnh (hay khối lệnh) statement3.
Ví dụ:
if (time < 10) { greeting = "Good morning"; } else if (time < 20) { greeting = "Good day"; } else { greeting = "Good evening"; }
Cũng là lệnh điều kiện giống if dùng để đưa ra những hành động khác nhau trong những điều kiện khác nhau, chúng ta có thể dùng lệnh switch trong Java.
Lệnh switch
Cú pháp:
switch (expression) { case value 1: statement1 break; …… case value n: statementn break; default: statements break; }
Sơ đồ khối
Ví dụ:
char grade = 'C'; switch(grade) { case 'A': System.out.println("Excellent!"); break; case 'B': case 'C': System.out.println("Well done"); break; case 'D': System.out.println("You passed"); case 'F': System.out.println("Better try again"); break; default: System.out.println("Invalid grade"); } System.out.println("Your grade is " + grade);
Một số lưu ý khi sử dụng lệnh switch:
– Chỉ dùng switch với các kiểu dữ liệu sơ cấp (primitive data types) như int hay String. Với các kiểu dữ liệu khác (bao gồm cả float và double), chúng ta phải dùng if.
– Nhãn cho mỗi case phải là hằng, như 42 hay “42”, nếu là một biểu thức cần được xử lý trong thời điểm run time thì phải sử dụng if.
– Mỗi nhãn cho mỗi case phải là duy nhất.
– Nếu muốn thực hiện một (hay khối) lệnh cho nhiều giá trị nhãn case, chúng ta có thể cung cấp một danh sách các nhãn case liên tục (không bị ngắt bởi các lệnh hay break) và các lệnh thực thi cho nhãn case cuối cùng cũng chính là cho tất cả các nhãn trong danh sách. Ví dụ: nếu biến ch nhận các giá trị “a”, “b”, “c” thì xuất ra màn hình “Hello”
char ch; switch (ch) { case "a": case "b": case "c": System.out.println ("Hello"); break; }
Nếu viết như sau sẽ bị lỗi:
char ch; switch (ch) { case "a": case "b": System.out.println ("Hello"); case "c": System.out.println ("Hello"); break; }
Lệnh lặp
Trong lập trình, có những lệnh hay khối lệnh được lặp lại nhiều lần. Thay vì viết các lệnh hay khối lệnh này nhiều lần, chúng ta có thể dùng các lệnh lặp. Java hỗ trợ các lệnh lặp while, do, for.
Lệnh lặp while
Lệnh while sẽ lặp theo một điều kiện nào đó. Chừng nào biểu thức điều kiện logical expression còn đúng thì lệnh lặp sẽ vẫn thực thi lệnh (hay khối lệnh) statement. Cú pháp:
while (logical expression) { statement }
Sơ đồ khối
Ví dụ hiển thị các giá trị từ 0 đến 9:
int i = 0; String numseq = ""; while (i < 10) { numseq += " " + i; i = i + 1; // or i++; } System.out.println("The number sequence is "+ numseq);
Sai lầm phổ biến của những người bắt đầu dùng while là quên dòng lệnh i = i + 1. Biến i trong ví dụ trên đóng vai trò như lính canh (sentinel) để giúp vòng lặp hữu hạn. Biến i còn gọi là sentinel variable.
Lệnh lặp for
Dùng để lặp theo một số lần xác định cho trước, ví dụ thực hiện lệnh xuất dòng chữ Hello 5 lần. Cú pháp:
for (initial expression; logical expression; update expression) { statement }
initial expression, logical expression, update expression là còn gọi là các biểu thức điều khiển và chúng cách nhau bởi dấu chấp phẩy. initial expression là biểu thức khởi tạo giá trị để bắt đầu lặp, logical expression là biểu thức điều kiện để thực hiện lệnh (hay khối lệnh) statement, update expression là biểu thức cập nhật giá trị sau khi thực hiện statement, nếu logical expression vẫn còn true thì for sẽ tiếp tục thực thi statement.
Sơ đồ khối
Hiển thị các số từ 1 đến 10
int i; String numseq = ""; for (i = 1; i <= 10; i++) { numseq += " " + i; } System.out.println("The number sequence is "+ numseq);
Hiển thị các số chẵn trong dãy số nguyên từ 0 đến 10
int i; String numseq = ""; for (i = 0; i <= 10; i = i + 2) { numseq += " " + i; } System.out.println("The even sequence is "+ numseq);
Chúng ta có thể bỏ qua các thành phần initial expression, logical expression, update expression trong for, cụ thể, nếu chúng ta bỏ logical expression tức là chúng ta mặc định giá trị của nó là true thì vòng lặp for sẽ lặp vô hạn như ví dụ:
for (i = 0;;i++) { System.out.println ("somebody stop me!"); }
Nếu chúng ta bỏ qua initial expression và update expression thì for sẽ trông như while như ví dụ sau:
int i = 0; for (; i < 10;) { System.out.println (i); i++; }
Có thể có nhiều biểu thức khởi tạo initial expression và nhiều biểu thức cập nhật update expression như ví dụ sau:
for (i = 0, j = 10; i <= j; i++, j--) { ... }
Chúng ta có thể khai báo một biến trong biểu thức initial expression với lưu ý:
– Không thể dùng biến này sau khi vòng lặp for kết thúc, ví dụ:
for (int i = 0; i < 10; i++) { ... } System.out.println (i); // error
– Có thể khai báo trùng tên biến (trùng kiểu) cho các for khác nhau, ví dụ:
for (int i = 0; i < 10; i++) { ... } for (int i = 0; i < 20; i += 2) // okay { ... }
Có thể dùng for để duyệt và nhận thông tin từ các phần tử của một đối tượng tập hợp (tương tự lệnh foreach trong C#)
Cú pháp:
for (element : collection) { statement }
Ví dụ:
int[] fibarray = new int[] { 0, 1, 1, 2, 3, 5, 8, 13 }; for (int element : fibarray) { System.out.print(" "+ element); }
Lệnh lặp do
Lệnh while và for kiểm tra biểu thức điều kiện đầu tiên để bắt đầu lặp, nghĩa là, nếu biểu thức điều kiện là false thì các lệnh trong vòng lặp sẽ không được thực hiện. Lệnh lặp do thì khác; biểu thức điều kiện sẽ được kiểm tra sau mỗi lần lặp nên các lệnh trong lệnh lặp do sẽ thực hiện ít nhất một lần. Cú pháp:
do { statement } while (logical expression);
Sơ đồ khối
Xét ví dụ sau để phân biệt while và do:
Đoạn mã sau sẽ không thực thi vì i = 11 >10
int i = 11; String numseq = ""; while (i < 10) { numseq += " " + i; i = i + 1; } System.out.println("The number is " + numseq);
Đoạn mã sau sẽ thực thi và kết quả là The number is 11
int i = 11; String numseq = ""; do { numseq += " " + i; i = i + 1; } while (i < 10); System.out.println("The number is " + numseq);
Lệnh thoát vòng lặp
Có thể thoát khỏi vòng lặp while, do hay for bằng lệnh break. Ví dụ: vòng lặp sau sẽ thoát khi i = 5, tức là chỉ xuất các giá trị từ 1 đến 4
for (int i = 1; i <= 10; i++) { if (i == 5) { break; } numseq += " " + i; } System.out.println(numseq);
Có thể bỏ qua một lần lặp để chuyển qua lần lặp kế tiếp bằng lệnh continue. Ví dụ xuất từ 1 đến 10 nhưng bỏ số 5:
for (int i = 1; i <= 10; i++) { if (i == 5) { continue; } numseq += " " + i; } System.out.println(numseq);
Debugging
Debugging là thuật ngữ dùng để chỉ khả năng kiểm tra, phát hiện lỗi, sửa lỗi và bảo trì mã chương trình. Đây là một trong những kỹ năng quan trọng nhất của người lập trình. Lời khuyên tốt nhất cho những người mới học lập trình Java trong môi trường Eclipse là, khi chạy một chương trình, nên sử dụng nút Debug thay vì sử dụng nút Run:
Giá trị của các biến
Hình thức đơn giản nhất để kiểm tra giá trị của các biến là hiển thị các giá trị này ra màn hình bằng phương thức, ví dụ System.out.print(). Tuy nhiên, môi trường Eclipse hỗ trợ chúng ta nhiều công cụ hữu ích giúp chúng ta debugging một cách hiệu quả. Giả sử chương trình Java của chúng ta như sau:
public static void main(String[] args) { // TODO Auto-generated method stub int i; String numseq = ""; for (i = 1; i <= 3; i++) { numseq += " " + i; } System.out.println(numseq); }
Bây giờ chúng ta sẽ khám phá một số công cụ phục vụ quá trình debugging trong Eclipse.
Thiết lập điểm dừng (breakpoint)
Điểm dừng là vị trí chương trình sẽ tạm dừng và cho phép chúng ta quan sát những gì đang diễn ra trong các đoạn mã chương trình. Ví dụ chúng ta muốn thiết lập điểm dừng tại lệnh gán đến biến numseq trong for như sau:
Kích chuột phải vào lề trái của Eclipse tại dòng lệnh và chọn Toggle Breakpoint
Một điểm dừng sẽ được thiết lập:
Điểm dừng có màu xanh tức là nó đang hoạt động (phân biệt với điểm dừng màu trắng) và chương trình sẽ tạm dừng khi đến điểm dừng. Chúng ta có thể cho điểm dừng ngừng hoạt động bằng cách nhấn chuột phải lên điểm dừng và chọn Disable Breakpoint:
Lúc này điểm dừng sẽ chuyển sang màu trắng:
Và chương trình sẽ vẫn hoạt động bình thường khi đến điểm dừng.
Debug perspective trong Eclipse
Khi thực thi chương trình bằng nút Debug, nếu chương trình bắt gặp điểm dừng, một hộp thoại yêu cầu chúng ta chuyển sang chế độ Debug xuất hiện:
Chọn Remember my decision và nhấn Yes. Lúc này Eclipse sẽ chuyển chúng ta đến khung nhìn mới với nhiều công cụ hỗ trợ chúng ta debugging
Để ý dòng lệnh của chúng ta lúc này có dấu mũi tên chồng lênh điểm dừng:
Nếu quan sát trên thanh công cụ của Eclipse, chúng ta sẽ thấy ba nút nhấn quan trọng là Resume– cho phép chương trình thực thi bình thưởng, Suspend
– tạm dừng chương trình khi nó đang thực thi nhưng chưa gặp điểm dừng , và Terminate
– ngừng thực thi chương trình (các phiên bản Eclipse cũ hơn sẽ là Play, Pause, và Stop).
Chúng ta có thể chuyển đổi qua lại giữa chế độ bình thường và chế độ debugging bằng cách nhấn các nút ở gốc phải trên trên thanh công cụ Eclipse:
Step Over và Step Into
Khi chương trình tạm dừng, chúng ta có thể xem sự thay đổi các giá trị của tất cả các biến trong chương trình khi nó thực hiện một lần tại một thời điểm bằng chức năng Step Over và Step Into
trên thanh công cụ của Eclipse:
Với Step Over, chương trình sẽ thực thi dòng mã hiện tại và tạm ngừng trở lại. Nếu dòng mã hiện tại là lệnh gọi một phương thức thì Step Over xem lệnh này như một lệnh bình thường và sẽ không nhảy vào trong phần thân của phương thức. Step Into tương tự Step Over nhưng nếu lệnh hiện tại là lệnh gọi một phương thức thì chương trình sẽ nhảy vào phần thân phương thức và dừng.
Cửa sổ Variables
Với Step Over và Step Into, chúng ta có thể xem sự thay đổi giá trị của các biến qua cửa sổ Variables:
Lúc này, nếu nhấn Step Over thì kết quả:
Dòng lệnh lúc này:
Với những công cụ đơn giản mà hiệu quả trong Eclipse, chúng ta có thể dễ dàng debugging chương trình của mình.
Lệnh assert
Lệnh assert là lệnh hữu ích khi debugging hay testing. Lệnh assert dùng để đảm bảo một điều kiện luôn đúng, nếu điều kiện sai, chương trình sẽ dừng và cảnh báo lỗi. Mặc định, Eclipse bỏ qua lệnh assert. Để sử dụng tính năng của lệnh assert, chúng ta vào Run > Run Congigurations, chọn dự án (Project) và lớp cần áp dụng lệnh assert. Tính năng dùng cho lệnh assert được gọi là enable assertions và viết tắt là ea.
Để hiểu hơn cách dùng lệnh assert, giả sử chúng ta có lớp MainClass trong dự án MyFirstProject như sau:
public class MainClass { public static void main(String[] args) { // TODO Auto-generated method stub int so_bi_chia;// số bị chia int so_chia;// số chia Scanner scanner = new Scanner(System.in); System.out.println("Nhap so bi chia: "); so_bi_chia = Integer.parseInt(scanner.nextLine()); System.out.println("Nhap so chia: "); so_chia = Integer.parseInt(scanner.nextLine()); //Đảm bảo số chia phải khác 0 assert(so_chia != 0); // In ra kết quả nếu số chia đảm bảo khác 0 System.out.println(so_bi_chia + " / " + so_chia + " = " + (so_bi_chia / so_chia) + " So du là: " + (so_bi_chia % so_chia)); } }
Khi thực thi chương trình:
Nhap so bi chia: 3 Nhap so chia: 0
Kết quả sẽ phát sinh một ngoại lệ (vấn đề ngoại lệ sẽ tìm hiểu trong chương IX):
Exception in thread "main" java.lang.ArithmeticException: / by zero at MainPackage.MainClass.main(MainClass.java:20)
Và nếu chúng ta Debug chương trình:
Lúc này chương trình sẽ highlight dòng lệnh trực tiếp gây ra lỗi. Dùng lệnh assert bằng cách vào Run > Run Configurations, chọn MainClass trong dự án MyFirstProject:
Chọn tab (x)= Arguments. Nhập –ea trong VM arguments:
Nhấn Apply và Close. Nếu chúng ta thực thi lại chương trình (vẫn dùng các input là 3 và 0) bằng Run sẽ phát sinh ngoại lệ:
Exception in thread "main" java.lang.AssertionError at MainPackage.MainClass.main(MainClass.java:17)
Nếu dùng Debug chương trình sẽ highlight ngay tại lệnh assert để chúng ta có thể phát hiện và điều chỉnh lỗi:
Lệnh assert cũng rất hữu ích trong testing (ví dụ Unit Testting).