24/05/2018, 15:42

Các lệnh điều khiển dòng thực hiện và xử lý ngoại lệ trong ngôn ngữ lập trình Java

Nội dung: Các câu lệnh điều khiển dòng rẽ nhánh chương trình: lệnh chọn if, if- else, switch ; Các câu lệnh lặp while, do-while, for, Các lệnh thay đổi điều khiển chương trình : break, continue, return; ...

Nội dung:

  • Các câu lệnh điều khiển dòng rẽ nhánh chương trình: lệnh chọn if, if- else, switch;
  • Các câu lệnh lặp while, do-while, for,
  • Các lệnh thay đổi điều khiển chương trình: break, continue, return;
  • Cấu trúc lệnh xử lý hoặc cho qua các ngoại lệ: try-catch-finally, lệnh throw, Các lớp đối tượng xử lý ngoại lệ.

Các câu lệnh điều khiển rẽ nhánh chương trình

Java cung cấp các lệnh rẽ nhánh (tuyển chọn) để có thể chọn các phương án khác nhau trong quá trình thực hiện của chương trình. Có ba loại lệnh rẽ nhánh để thực hiện: lệnh if đơn giản, if - else switch.

Câu lệnh if đơn giản

Câu lệnh if đơn giản (lệnh if) có dạng cú pháp qui định:

  • if <Biểu thức điều kiện>
  • <Câu lệnh> // (1)
  • Câu lệnh if-else

    Cú pháp của lệnh if-else có dạng:

  • if <Biểu thức điều kiện>
  • <Câu lệnh 1> // (2)
  • else
  • <Câu lệnh 2> //(3)
  • Các câu lệnh if- else có thể lồng nhau, nhưng khi đó chúng phải lồng nhau thực sự và không được cắt nhau. Chúng phải tuân theo qui tắc sau:
  • Qui tắc: Câu lệnh else luôn sánh với câu lệnh if gần nhất nếu câu lệnh đó chưa có lệnh else tương ứng.

        if (nhietDo >= canTren) { // (1)
        	if (nguyHiem) baoDong; // (2) Lệnh if đơn giản
        	if (coNguyCo) // (3)
        		tinhToan();
        	else // ứng với lệnh if ở (3)
        		tatLoNhiet();
        } else // ứng với lệnh if (1)
        choLoNhietChay();
        

    Câu lệnh switch

    Câu lệnh này cho phép rẽ nhánh theo nhiều nhánh tuyển chọn dựa trên các giá trị kiểu nguyên của biểu thức. Nó có dạng:

  • switch (<Biểu thức nguyên>) {
  • case nhan1: <Câu lệnh 1>
  • case nhan2: <Câu lệnh 2>
  • . . .
  • case nhann: <Câu lệnh n>
  • default: <Câu lệnh >
  • }
  • Cách thực hiện như sau:

    1. Trước tiên tính giá trị của <Biểu thức nguyên>
    2. So sánh giá trị tính được với các nhani, i = 1, 2, ... n. Nếu giá trị đó bằng nhani thì thực hiện nhánh câu lệnh <Câu lệnh i> tương ứng. Sau khi thực hiện xong thì chuyển tiếp tới các lệnh sau đó theo điều khiển chương trình (nếu có break thì chuyển tới sau lệnh switch).
    switch

    Các câu lệnh switch có thể lồng nhau.

    Các lệnh switch lồng nhau.
    public class Mua {
        public static void main(String args[]){
        	int thang = 9;
       	 switch (thang) { // Khối ngoài (1)
        		case 11:
        		case 12:
        		case 1:
        			System.out.println("Mua dong");
        			break;
        		case 2: case 3: case 4:
        			System.out.println("Mua xuan");
        			break;
        		case 5: case 6: case 7:
        			System.out.println("Mua he");
        			break;
        		case 8: case 9: case 10:
        		switch(thang){ // Khối bên trong (2)
        			case 8:
        				System.out.println("Dau mua thu");
        				break;
        			case 9:
        				System.out.println("Hoc sinh den truong");
        				break;
        		}
        		System.out.println("Mua thu la vang roi!");
        		break;
        		default:
        		System.out.println(thang + " khong phai la thang");
        		}
        	}
        }
        

    Các câu lệnh lặp

    Câu lệnh lặp (chu trình) cho phép một khối các câu lệnh thực hiện một số lần lặp lại. Biểu thức boolean được sử dụng để kiểm tra xem khi nào chu trình lặp kết thúc, được gọi là điều kiện kết thúc chu trình. Trong Java có ba cấu trúc điều khiển lặp:

    • Câu lệnh while,
    • Câu lệnh do-while,
    • Câu lệnh for.

    Câu lệnh while (chu trình while)

  • Câu lệnh while có dạng:

  • while (<Điều kiện kết thúc chu trình>)

    <Thân chu trình>

    Câu lệnh do-while (chu trình do-while)

    Câu lệnh do-while có dạng:

    do

    <Thân chu trình>

    while (<Điều kiện kết thúc chu trình>)

  • (Thân chu trình) phải thực hiện ít nhất một lần.

    Câu lệnh for (chu trình for)

  • Chu trình for là dạng tổng quát nhất của các câu lệnh lặp. Nó thường được sử dụng để điều khiển quá trình lặp khi số các lần lặp được biết trước. Chu trình for có dạng:

  • for (<Biểu thức bắt đầu>; <Điều kiện lặp>; <Biểu thức gia tăng>)

    <Thân chu trình>

  • <Biểu thức bắt đầu> chỉ thực hiện đúng một lần ngay khi câu lệnh for bắt đầu thực hiện. Hoạt động của chu trình for được mô tả như sau: for

    • Tất cả các biến được khai báo trong <Biểu thức bắt đầu> đều là cục bộ trong khối thân của chu trình for.
    • Các thành phần của chu trình for là tùy chọn. Một trong <Biểu thức bắt đầu>, <Biểu thức gia tăng>, <Điều kiện kết thúc> có thể trống.
    • Trường hợp <Điều kiện kết thúc> là trống thì điều kiện lặp của chu trình được xem là true.
    • for (; ; ) được sử dụng để xây dựng chu trình lặp vô điều kiện.

    Các câu lệnh chuyển vị

    Java cung cấp bốn cách để chuyển điều khiển thực hiện của chương trình:

    • break
    • continue
    • return
    • try-catch-finally

    Câu lệnh break

    • Câu lệnh break được sử dụng trong các khối được gắn nhãn, trong các chu trình lặp (for, while, do-while) và câu lệnh switch để chuyển điều khiển thực hiện chương trình ra khỏi khối trong cùng chứa nó.
    • Trong trường hợp khối được gắn nhãn, khi gặp lệnh break thì phần còn lại của khối bị cho qua và chương trình tiếp tục thực hiện lệnh đứng sau khối đó,
    • Đối với các chu trình lặp, khi gặp lệnh break thì phần còn lại của thân chu trình được bỏ qua và kết thúc chu trình đó,
    • Đối với lệnh switch, khi gặp lệnh break thì phần còn lại của lệnh switch bị bỏ qua và tiếp tục thực hiện lệnh đứng sau lệnh switch đó.
    Chương trình minh hoạ cách sử dụng khối được gắn nhãn và lệnh break
    // Tệp Label.java
        class Label {
        public static void main(String args[]){
        	int[][] sqMatrix = {{4,3,5},{2,1,6},{9,7,8}};
        	int sum = 0;
        	outer: // Gắn nhãn outer cho khối
        	for (int i = 0; i < sqMatrix.length; i++){ // (1)
        		for(int j = 0; j < sqMatrix[i].length; i++){// (2)
        			if (i == j) break;// Kết thúc chu trình (2) và tiếp ở (5)
        				System.out.println("Bang["+i+","+j+"] = "
        				+ sqMatrix[i][j]);
        				sum += sqMatrix[i][j];
        			if (sum >10) break outer;// Kết thúc khối outer (cả   			// hai chu trình for) và chuyển tới (6)
        		} // Kết thúc for bên trong  // (5)
              } // Kết thúc for bên ngoài  // (6)
              System.out.println("Tong sum = " + sum);
        }
        }
        

    Kết quả thực hiện của chương trình:

    Bang[1, 0] = 2

    Bang[2, 0] = 9

    Tong sum = 11

    Câu lệnh continue

    • Câu lệnh continue được sử dụng trong các chu trình lặp for, while, do-while để dừng sự thực hiện của lần lặp hiện thời và bắt đầu lặp lại lần tiếp theo nếu điều kiện lặp còn thoả (còn true).
    • Đối với chu trình while, do-while, khi gặp continue thì phần còn lại của thân chu trình bị bỏ qua và tiếp tục kiểm tra điều kiện lặp để thực hiện quá trình lặp tiếp theo.
    • Đối với lệnh for, khi gặp continue thì phần còn lại của thân chu trình bị bỏ qua và tiếp tục thực hiện <Biểu thức gia tăng> sau đó thực hiện lặp lại nếu <Điều kiện kết thúc> còn true.
    Chương trình minh hoạ cách sử dụng lệnh continue để ngắt lần lặp hiện thời.

    Chương trình in ra màn hình các số 1, 2, 3 và 5 cùng với căn bậc 2 của chúng, còn với i = 4 thì không thực hiện.

     
    class TiepTuc {
    public static void main(String args[]){
    for (int i = 1; i <= 5; ++i){
    if (i == 4) continue;
    // Phần còn lại sẽ bị bỏ qua
    System.out.println(i + "	" + Math.sqrt(i));
    // Thực hiện ++i và kiểm tra để lặp lại
    }
    }
    }
        

    Câu lệnh return

    Câu lệnh return được sử dụng để kết thúc thực hiện của hàm hiện thời và chuyển điều khiển chương trình về lại sau lời gọi hàm đó. Lệnh này có hai dạng sử dụng tương ứng với hai loại hàm được xác định như trong bảng sau:

    Dạng lệnh return Hàm khai báovoid Hàm có kiểu trả lại khácvoid
    return Tùy chọn Không cho phép
    return <Biểu thức> Không cho phép Bắt buộc
    Chương trình minh hoạ các lệnh return

    Kiểm tra xem số các đối số của chương trình có bằng 0 và in ra số đó nếu lớn hơn 3, ngược lại in ra số 2 khi có đối số.

    class Label {
        public static void main(String args[]){
        	if (args.length == 0) return;// Tùy chọn
        		output(check(args.length));
        	}
        	static void output(int val){//
        		System.out.println(val);
        		// return 1; Không được phép vì output() kiểu void
        	}
        static int check(int i) {
        	if (i > 3) return i;
        	else return 2;// Nếu là return 2.0 sẽ sai vì không tương thích kiểu
        	}
        }
        

    Câu lệnh try-catch-finally được sử dụng chủ yếu để xử lý các ngoại lệ. Câu lệnh này được đề cập chi tiết ở mục sau.

    • Mục đích của công nghệ phần mềm là: Xây dựng các module phần mềm tốt, đảm bảo chúng làm việc được trong mọi tình huống và dễ dàng thích ứng với mọi điều kiện. Muốn đảm bảo hệ thống có được những tính chất trên thì phải có cơ chế để xử lý được tất cả các ngoại lệ, các tình huống liên qua tới phạm vi xác định của các phần tử trong các cấu trúc dữ liệu.
    • Một ngoại lệ (exception) trong chương trình Java là dấu hiệu chỉ ra rằng có sựxuất hiện một điều kiện không bình thường nào đó.
    • Java cung cấp một cơ chế để kiểm tra một cách có hệ thống các điều kiện ngoại lệ. Để xử lý ngoại lệ trong Java, chúng ta sử dụng khối lệnh try-catch-finally.

    Các khối lệnh try, catch và finally

    Cấu trúc try-catch-finally cho phép sử dụng để xử lý các ngoại lệ có dạng:

  • try { // Khối try
  • <Các câu lệnh>
  • } catch (<Kiểu ngoại lệ 1> <Tham biến 1>) { // Khối catch
  • <Các câu lệnh xử lý khi xuất hiện kiểu ngoại lệ 1>
  • }
  • . . .
  • catch (<Kiểu ngoại lệ n> <Tham biến n>) { // Khối catch
  • <Các câu lệnh xử lý khi xuất hiện kiểu ngoại lệ n>
  • } finally {
  • < Các câu lệnh phải thực hiện đến cùng> // Khối finally
  • }
    • Các ngoại lệ sẽ được cho qua trong quá trình thực hiện khối try và sẽ bị tóm lại để xử lý ở các khối catch tương ứng. Khối finally phải thực hiện đến cùng, bất luận có gặp phải ngoại lệ hay không.
    • Hoạt động của các khối trên được minh hoạ như sau:
    Hoạt động của khối try - catch

    Khối try

    • Khối try xác định ngữ cảnh cần xử lý sự kết thúc thực hiện của một khối lệnh. Sự kết thúc thực hiện của khối lệnh xuất hiện khi: Gặp phải một ngoại lệ, Hoặc thực hiện thành công khối try (không gặp ngoại lệ).
    • Thực hiện xong khối try và xử lý xong các ngoại lệ khi chúng xuất hiện thì phải thực hiện khối finally nếu nó được chỉ ra trong cấu trúc đó.

    Khối catch

    • Lối ra của khối try khi gặp phải ngoại lệ có thể chuyển điều khiển chương trình đến khối catch. Khối này chỉ được sử dụng để xử lý ngoại lệ. Khi một khối catch được thực hiện thì các khối catch còn lại sẽ bị bỏ qua.
    • Trong trường hợp khối finally không xuất hiện thì chúng ta có cấu trúc try-catch.
    Cấu trúc try-catch
    public class ChiaChoKhong {
        public void chia(){
        	int n1 = 20;
        	int n2 = 0;
        	try {
        		System.out.println(n1+" / "+n2+" = "+(n1/n2));
        	} catch (ArithmeticException e) { // (1)
        		System.out.println("Gap phai loi: "+e); // (2)
        	}
        	System.out.println("Ket thuc ham chia()");
        } // (3)
        public static void main(String args[]){
        	new ChiaChoKhong().chia(); // (4)
        	System.out.println("Quay lai tu ham main!"); // (5)
        }
        }
        

    Khối finally

    Khi khối finally có trong đặc tả khối try-catch-finally thì nó được đảm bảo phải thực hiện đến cùng bất luận trong khối try thực hiện như thế nào.

    Cấu trúc try-catch-finally
    public class ChiaChoKhong1 {
        public void chia(){
        	int n1 = 20;
        	int n2 = 0;
        	try {
        		System.out.println(n1+" / "+n2+" = "+(n1/n2)); // (1)
        	} catch (ArithmeticException e) { // (2)
        		System.out.println("Gap phai loi: "+e);
        	}finally { // (3)
        		System.out.println("Nhung viec can thuc hien");
        	}
        		System.out.println("Ket thuc ham chia()"); // (4)
        	}
        public static void main(String args[]){
        	new ChiaChoKhong1().chia(); // (5)
        	System.out.println("Quay lai tu ham main!"); // (6)
        }
        }
        

    Kết quả thực hiện của chương trình ChiaChoKhong1:

    Gap phai loi: java.lang.ArithmeticException: /by zero

    Nhung viec can thuc hien

    Ket thuc ham chia()

    Quay lai tu ham main!

  • Khi không sử dụng khối catch để xử lý các ngoại lệ thì khối finally vẫn phải được thực hiện nhưng sau đó các phần còn lại của chương trình sẽ không được thực hiện nếu xuất hiện những ngoại lệ tệ hại như chia cho 0.
  • Cấu trúc try-finally
    public class ChiaChoKhong2 {
        	public void chia(){
        		int n1 = 20;
        		int n2 = 0;
        		try {
        			System.out.println(n1+" / "+n2+" = "+(n1/n2)); // (1)
        		}finally { // (2)
        			System.out.println("Nhung viec can thuc hien");
        		}
        		System.out.println("Ket thuc ham chia()"); // (3)
        	}
        public static void main(String args[]){
        	new ChiaChoKhong2().chia(); // (4)
        	System.out.println("Quay lai tu ham main!"); // (5)
        	}
        }
        

    Kết quả thực hiện của chương trình ChiaChoKhong2:

  • Nhung viec can thuc hien

    Gap phai loi: java.lang.ArithmeticException: /by zero

    at ChiaChoKhong2.chia(ChiaChoKhong2.java)

    ChiaChoKhong2.main(ChiaChoKhong2.java)

  • Câu lệnh throw

    Để tạm thời bỏ qua ngoại lệ chúng ta có thể sử dụng câu lệnh throw. Câu lệnh này có dạng như sau:

    throw <Biểu thức tham chiếu đối tượng ngoại lệ>

    • <Biểu thức tham chiếu đối tượng ngoại lệ> là biểu thức xác định một đối tượng của lớp Throwable hoặc của một trong các lớp con của nó. Thông thường một đối tượng ngoại lệ sẽ được tạo ra trong câu lệnh throw để sau đó chúng sẽ được tóm lại và xử lý ở khối catch.

      Ví dụ câu lệnh throw new ChiaCho0Exception(“ / by zero”); Trong đó lớp ChiaCho0Exception là lớp con của Exception có thể định nghĩa đơn giản như sau:

          class ChiaCho0Exception extends Exception {
                ChiaCho0Exception(String msg) {super(msg);}
          }
          
    • Khi một ngoại lệ xuất hiện và được cho qua thì sự thực hiện bình thường của chương trình sẽ bị treo lại để đi tìm khối catch tương ứng và xử lý ngoại lệ đó.
    • Sau đó khối finally được thực hiện nếu có. Nếu không tìm thấy bộ xử lý ngoại lệ tương ứng trong chương trình thì ngoại lệ đó được xử lý theo cơ chế xử lý ngoại lệ mặc định của hệ thống.
    Câu lệnh tạm thời cho qua ngoại lệ
    class ChiaCho0Exception extends Exception {
        ChiaCho0Exception(String msg) {super(msg);}
        }
        public class ChiaChoKhong3 {
        	public void chia(){
        	int n1 = 20;
        	int n2 = 0;
       	 try { // (1)
        		if(n2 == 0)throw new ChiaCho0Exception(“/ by 0”);// (2)
        		System.out.println(n1+" / "+n2+" = "+(n1/n2)); // (3)
        	}catch (ChiaCho0Exception er){ // (4)
       		 System.out.println("Gap loi: " +er);
        	}finally {
        		System.out.println("Nhung viec can thuc hien");// (5)
        	}
        	System.out.println("Ket thuc ham chia()"); // (6)
        }
        public static void main(String args[]){
        	new ChiaChoKhong3().chia();
        	System.out.println("Quay lai tu ham main!"); // (7)
        	}
        }
        

    Kết quả thực hiện của chương trình ChiaChoKhong3:

    Gap phai loi: ChiaChoException: /by zero

    Nhung viec can thuc hien

    Ket thuc ham chia()

    Quay lai tu ham main!

    Trong ví dụ 4.8, khối try (1) trong hàm chia() tạm thời cho qua ngoại lệ xuất hiện ở (2).

    Lưu ý phần còn lại (3) của khối try không được thực hiện.

    Khối finally (5) được thực hiện sau đó tiếp tục thực hiện bình thường các lệnh (6), (7).

    Mệnh đề throws

    Khi thiết kế các hàm thành phần, chúng ta có thể sử dụng mệnh đề throws để tạm thời cho qua ngoại lệ mà thực hiện một số công việc cần thiết khác. Những hàm này lại được sử dụng theo cấu trúc try-catch-finally sau đó để xử lý các ngoại lệ khi chúng xuất hiện như trên. Chương trình dịch có thể cho qua những lỗi ngoại lệ đã phát hiện nếu trong định nghĩa các hàm có sử dụng kết hợp với mệnh đề throws. Định nghĩa hàm với mệnh đề throws có dạng:

  • <Thuộc tính của hàm> <tên hàm>(<Danh sách các tham biến>) throws <Danh sách các kiểu ngoại lệ> { /* ... */}

  • Trong đó <Danh sách các kiểu ngoại lệ> là các lớp xử lý ngoại lệ được kế thừa từ lớp Exception và được phân tách bởi dấu ‘,’.
    class A{
        protected void classMethA() throws FirstException, SecondException{
        /* . . . */
        }
        
  • Mô tả cách sử dụng mệnh đề throws trong định nghĩa hàm
    class ChiaCho0Exception extends Exception { // (1)
        ChiaCho0Exception(String msg) {super(msg);}
        }
        public class ChiaChoKhong4 {
        public void chia() throws ChiaCho0Exception { // (2)
        int n1 = 20;
        int n2 = 0;
        if(n2 == 0)throw new ChiaCho0Exception(“/ by 0”); // (3)
        System.out.println(n1+" / "+n2+" = "+(n1/n2));
        System.out.println("Ket thuc ham chia()");
        }
        public static void main(String args[]){
        try {
        new ChiaChoKhong3().chia(); // (4)
        }catch (ChiaCho0Exception er){
        System.out.println("Trong main() gap loi: " +er);
        }finally {
        System.out.println("Nhung viec can thuc hien");// (5)
        }
        System.out.println("Quay lai tu ham main!"); // (7)
        }
        }
        

    Chương trình thực hiện và cho kết quả:

    Trong main() gap loi: ChiaCho0Exception: / by 0

    Nhung viec can thuc hien

    Quay lai tu ham main!

    Khi xây dựng hệ thống thường có rất nhiều loại lỗi (ngoại lệ) khác

    nhau có thể xảy ra. Để tiện lợi cho việc kiểm soát chúng, người lập

    trình nên đặt tên cho từng loại ngoại lệ đó cho phù hợp với ngữ cảnh mà chúng xuất hiện và sao cho dễ nhớ.

    1. Viết chương trình tạo dãy số nguyên ngẫu nhiên có giá trị khác nhau.
    2. Viết chương trình giải phương trình bậc II dạng:
    3. ax2 + bx + c = 0
    4. Viết chương trình giải bất phương trình bậc II dạng
    5. ax2 + bx + c > 0
    6. Thử giải hệ phương trình theo một phương pháp nào đó.
    7. Viết chương trình mô phỏng một máy tính có thể dùng để thực hiện các phép tính số học. tính số học.
    0