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): ifswitch      

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ả floatdouble), 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 expressionupdate 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 whilefor 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 whiledo:

Đ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 OverStep 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 OverStep 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 ApplyClose. 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).

Ngôn ngữ Java >