Exception Handling (Exception တွေကို ကိုင်တွယ်ခြင်း)

B2.1.3 - Describe how programs use common exception handling techniques.
မြန်မာလို: Program တွေက exception (program run နေစဉ် ဖြစ်တဲ့ အမှား) တွေကို ကိုင်တွယ်ဖို့ အသုံးများတဲ့ နည်းလမ်းတွေကို ဘယ်လို သုံးလဲဆိုတာ ဖော်ပြရှင်းပြနိုင်ရပါမယ်။


အဓိက အယူအဆများ

Program တွေမှာ run နေစဉ် (runtime) အမှား ဖြစ်နိုင်ပါတယ်: ဂဏန်း ရိုက်ရမယ့် နေရာမှာ user က စာသား ရိုက်ထည့်နိုင်တယ်၊ file တစ်ခု မရှိတာ ဖြစ်နိုင်တယ်၊ ဒါမှမဟုတ် တွက်ချက်မှု တစ်ခုက သုညနဲ့ စားမိနိုင်တယ်။ Exception handling က program ကို crash (program ရုတ်တရက် ပျက်ပြီး ရပ်သွားခြင်း) မဖြစ်စေဘဲ သင့်တော်တဲ့ နည်းနဲ့ တုံ့ပြန်နိုင်အောင် လုပ်ပေးပါတယ်။

try-catch-finally ဖွဲ့စည်းပုံ

try {
    // code that might throw an exception
} catch (ExceptionType e) {
    // code that runs if that exception is thrown
} finally {
    // code that ALWAYS runs - cleanup
}
try:
    # code that might raise an exception
    pass
except ValueError:      # Python says "except", not "catch" - name the specific error
    # code that runs if that exception is raised
    pass
finally:
    # code that ALWAYS runs - cleanup
    pass
Block ဘယ်အချိန် run သလဲ
try အမြဲ run ပါတယ်၊ အမှား ဖြစ်နိုင်တဲ့ code ကို ထုပ်ထားပါတယ်
catch သတ်မှတ်ထားတဲ့ exception ကို throw (exception ဖြစ်ကြောင်း အချက်ပြ) လုပ်မှသာ run ပါတယ်
finally အမြဲ run ပါတယ်၊ exception ဖြစ်ခဲ့ရင်တောင် run ပါတယ်

(Python keyword (programming language မှာ အထူး အဓိပ္ပာယ်ရှိတဲ့ စကားလုံး) တွေက try၊ except၊ finally ပါ။ except က catch ရဲ့ အလုပ်ကို လုပ်ပါတယ်။)

finally block ကို မထည့်လည်း ရပါတယ် (optional)၊ ဒါပေမယ့် ထည့်ထားရင် try အောင်မြင်တာ ဖြစ်ဖြစ်၊ catch run တာ ဖြစ်ဖြစ် အမြဲ run ပါတယ်။ File ပိတ်တာလို ရှင်းလင်းတဲ့ အလုပ် (cleanup) တွေအတွက် သုံးပါတယ်။

အဖြစ်များတဲ့ exception အမျိုးအစားများ

Exception ဘယ်အချိန် ဖြစ်သလဲ
InputMismatchException Scanner (keyboard ဒါမှမဟုတ် file ကနေ input ဖတ်တဲ့ Java class) က ဂဏန်း မျှော်လင့်ထားပေမယ့် စာသား ရလာတဲ့အခါ
ArrayIndexOutOfBoundsException Array (အရွယ်အစား ပုံသေ၊ အမျိုးအစားတူ ဒေတာစု) ရဲ့ အပိုင်းအခြား ပြင်ပက index (နေရာအမှတ်) ကို ယူသုံးတဲ့အခါ
ArithmeticException (ကိန်းပြည့်) သုညနဲ့ စားတဲ့အခါ
NullPointerException null reference (ဘာ object ကိုမှ မညွှန်းတဲ့ reference) ပေါ်မှာ method ခေါ်တဲ့အခါ
NumberFormatException ဂဏန်း မဟုတ်တဲ့ String ကို ဂဏန်းအဖြစ် ပြောင်းတဲ့အခါ
FileNotFoundException မရှိတဲ့ file ကို ဖွင့်တဲ့အခါ

(Python မှာ အနီးစပ်ဆုံး ညီမျှတာတွေက အပေါ်ကနေ အောက်ကို: ValueError၊ IndexError၊ ZeroDivisionError၊ AttributeError၊ int("abc") အတွက် ValueError ပဲ ထပ်ပြီး၊ FileNotFoundError တို့ ဖြစ်ပါတယ်။)


ဖြေရှင်းပြထားတဲ့ ဥပမာများ

ဥပမာ 1: အခြေခံ try-catch: user က မှားတဲ့ ဒေတာ ရိုက်ထည့်ခြင်း

import java.util.Scanner;
import java.util.InputMismatchException;

Scanner input = new Scanner(System.in);

try {
    System.out.print("Enter a whole number: ");
    int number = input.nextInt();
    System.out.println("Double that is: " + (number * 2));
} catch (InputMismatchException e) {
    System.out.println("Error: please enter a valid integer.");
}
try:
    number = int(input("Enter a whole number: "))
    print("Double that is:", number * 2)
except ValueError:      # int() raises ValueError when the text is not a number
    print("Error: please enter a valid integer.")

User က 42 ရိုက်ထည့်ရင်: Double that is: 84 ကို print ထုတ်ပါတယ် User က hello ရိုက်ထည့်ရင်: Error: please enter a valid integer. ကို print ထုတ်ပါတယ်

catch ပြီးတဲ့နောက် program က ဆက် run ပါတယ်၊ crash မဖြစ်ပါဘူး။


ဥပမာ 2: try-catch-finally: ရှင်းလင်းတဲ့ အလုပ်ကို သေချာ လုပ်ခြင်း

import java.util.Scanner;
import java.util.InputMismatchException;

Scanner input = new Scanner(System.in);

try {
    System.out.print("Enter a number: ");
    int num = input.nextInt();
    System.out.println("Result: " + (100 / num));
} catch (InputMismatchException e) {
    System.out.println("That's not a number!");
} catch (ArithmeticException e) {
    System.out.println("Cannot divide by zero!");
} finally {
    System.out.println("Program complete.");
}
try:
    num = int(input("Enter a number: "))
    print("Result:", 100 // num)     # // = whole-number division; 100 // 0 raises ZeroDivisionError
except ValueError:
    print("That's not a number!")
except ZeroDivisionError:
    print("Cannot divide by zero!")
finally:
    print("Program complete.")

အဓိက အချက်များ:

  • Exception အမျိုးအစား မတူတာတွေအတွက် catch block အများကြီး ထားလို့ရပါတယ်
  • ဘာပဲ ဖြစ်ဖြစ် finally block က "Program complete." ကို print ထုတ်ပါတယ်
  • User က 0 ရိုက်ထည့်ရင် ArithmeticException catch က run ပြီး၊ ပြီးတော့ finally run ပါတယ်

ဥပမာ 3: သုညနဲ့ စားခြင်း

int a = 10;
int b = 0;

try {
    int result = a / b;
    System.out.println("Result: " + result);
} catch (ArithmeticException e) {
    System.out.println("Error: cannot divide by zero.");
    System.out.println("Message: " + e.getMessage());
}
a = 10
b = 0

try:
    result = a // b
    print("Result:", result)
except ZeroDivisionError as e:      # "as e" captures the exception object
    print("Error: cannot divide by zero.")
    print("Message:", e)            # Python's wording differs from Java's "/ by zero":
                                    # "integer division or modulo by zero"

Output (program က ထုတ်ပြတဲ့ ရလဒ်):

Error: cannot divide by zero.
Message: / by zero

e.getMessage() က ဘာမှားသွားလဲဆိုတာကို တိုတိုလေး ဖော်ပြတဲ့ စာကို ပြန်ပေးပါတယ်။ ဒါက debugging (program ထဲက အမှားကို ရှာပြီး ပြင်ခြင်း) အတွက် အသုံးဝင်ပါတယ်။ (Python မှာ except ZeroDivisionError as e လို့ ရေးပြီး print(e) က အဲဒီ အလုပ်ကိုပဲ လုပ်ပေးပါတယ်။)


ဥပမာ 4: Input validation (ထည့်ပေးတဲ့ ဒေတာ မှန်မမှန် စစ်ခြင်း) loop နဲ့ try-catch

မှန်ကန်တဲ့ input ရတဲ့အထိ ဆက်မေးနေဖို့ exception handling ကို loop (ထပ်ခါထပ်ခါ run တဲ့ code အပိုင်း) နဲ့ ပေါင်းသုံးပါ။

import java.util.Scanner;
import java.util.InputMismatchException;

Scanner input = new Scanner(System.in);
boolean valid = false;
int number = 0;

while (!valid) {
    try {
        System.out.print("Enter an integer: ");
        number = input.nextInt();
        valid = true;
    } catch (InputMismatchException e) {
        System.out.println("Invalid! Please enter a whole number.");
        input.nextLine();  // clear the invalid input from the buffer
    }
}

System.out.println("You entered: " + number);
valid = False
number = 0

while valid == False:
    try:
        number = int(input("Enter an integer: "))
        valid = True
    except ValueError:
        print("Invalid! Please enter a whole number.")
        # no buffer to clear - input() always reads a fresh line

print("You entered:", number)

InputMismatchException ဖြစ်ပြီးတဲ့နောက် မမှန်တဲ့ input က Scanner buffer (ဖတ်ဖို့ ကျန်နေတဲ့ input ကို ခဏ သိမ်းထားတဲ့ နေရာ) ထဲမှာ ကျန်နေပါတယ်။ Loop နောက်တစ်ပတ် (iteration) မစခင် အဲဒါကို ရှင်းဖို့ input.nextLine() ကို ခေါ်ရပါမယ်၊ မဟုတ်ရင် loop က အဆုံးမရှိ run နေပါလိမ့်မယ်။ (Python ရဲ့ input() မှာတော့ buffer ထဲ ကျန်နေတဲ့ ပြဿနာ မရှိလို့ ရှင်းစရာ မလိုပါဘူး။)


ဥပမာ 5: မလုပ်သင့်တာ

// BAD - catching Exception hides all errors
try {
    // lots of code here...
} catch (Exception e) {
    // silently swallows every possible error
}
# BAD - a bare "except:" (or "except Exception:") hides all errors
try:
    # lots of code here...
    pass
except:
    # silently swallows every possible error
    pass

Code ထဲက မှတ်ချက်တွေ ပြောထားသလို Exception ကို catch လုပ်ရင် error အားလုံးကို ဖုံးထားမိပါတယ်: ဖြစ်နိုင်တဲ့ error တိုင်းကို ဘာမှ မပြောဘဲ မျိုချလိုက်သလို ဖြစ်ပါတယ်။ (Python မှာ ဘာမှ မတပ်ထားတဲ့ except: ဒါမှမဟုတ် except Exception: ကလည်း အတူတူပါပဲ။)

Exception ကို မဟုတ်ဘဲ တိကျတဲ့ exception တွေကို catch လုပ်ပါ။ အကုန်လုံးကို catch လုပ်ရင် bug (code ထဲက အမှား) တွေကို မမြင်ရတော့ဘဲ program ကို debug လုပ်ရ ပိုခက်သွားပါတယ်။


Quick Check (အမြန် စစ်ဆေးမေးခွန်း)

Q1. finally block က ဘယ်အချိန်မှာ run သလဲ။

Q2. try-catch နဲ့ ထုပ်ထားတဲ့ nextInt() call မှာ user က 'abc' လို့ ရိုက်ထည့်ရင် ဘာဖြစ်မလဲ။

Q3. int x = 10 / 0; က ဘယ် exception ကို throw လုပ်သလဲ။

Q4. try block တစ်ခုမှာ catch block အများကြီး ရှိလို့ ရသလား။

Q5. try block ရဲ့ line 2 က exception ကို throw လုပ်ရင် line 3 ဘာဖြစ်မလဲ။


Trace Exercise (code ကို တစ်ဆင့်ချင်း လိုက်ကြည့်ခြင်း)

ဒီ code ကို trace လုပ်ပါ။ ဘယ် line တွေ run သလဲ၊ ဘာတွေ print ထွက်သလဲ ဆုံးဖြတ်ပါ။ ဒုတိယ ကော်လံမှာ yes (run တယ်) ဒါမှမဟုတ် no (run မဘူး) ကို English လို ရိုက်ထည့်ပါ။

int x = 10;
int y = 0;

try {
    System.out.println("A");
    int result = x / y;
    System.out.println("B");
} catch (ArithmeticException e) {
    System.out.println("C");
} finally {
    System.out.println("D");
}
System.out.println("E");
x = 10
y = 0

try:
    print("A")
    result = x // y      # raises ZeroDivisionError
    print("B")
except ZeroDivisionError:
    print("C")
finally:
    print("D")
print("E")
LineRun သလား။ဘာကြောင့်လဲ။
println("A") Exception မဖြစ်ခင်မှာ ရှိလို့
x / y ArithmeticException ကို throw လုပ်ပါတယ်
println("B") ကျော်သွားပါတယ်: try ထဲမှာ exception ဖြစ်ပြီးနောက်မှာ ရှိလို့
println("C") Catch block run ပါတယ်
println("D") Finally က အမြဲ run ပါတယ်
println("E") try-catch-finally ပြီးနောက်မှာ ရှိလို့

Output အပြည့်အစုံက ဘာလဲ။ Print ထွက်တဲ့ အစဉ်အတိုင်း စာလုံးတွေကို line တစ်ကြောင်းတည်းမှာ ကြားမှာ space တစ်ခုစီ ခြားပြီး ရေးပါ။


Code Completion (code ကွက်လပ် ဖြည့်ခြင်း)

ဒီ code က keyboard ကနေ user ရဲ့ အသက်ကို ဖတ်ပြီး user က ဂဏန်းအစား ဂဏန်း မဟုတ်တဲ့ စာသား ရိုက်ထည့်တဲ့ အခြေအနေကို try-catch block နဲ့ သင့်တော်အောင် ကိုင်တွယ်ပါတယ်။ Exception handling ဖွဲ့စည်းပုံ ပြည့်စုံအောင် ပျောက်နေတဲ့ keyword တွေကို ဖြည့်ပါ။

import java.util.Scanner;
import java.util.InputMismatchException;

Scanner input = new Scanner(System.in);
 {
    System.out.print("Enter age: ");
    int age = input.nextInt();
    System.out.println("Age: " + age);
}  (InputMismatchException e) {
    System.out.println("Please enter a number!");
}

Spot the Error (အမှား ရှာခြင်း)

ဒီ code က ArithmeticException ပါတဲ့ try-catch ကို သုံးပြီး သုညနဲ့ စားတာကို catch လုပ်ရမှာပါ၊ ဒါပေမယ့် catch block က ဘယ်တော့မှ မ run ပါဘူး။ ဒီ bug က Java က integer (ကိန်းပြည့်) ကို သုညနဲ့ စားတာနဲ့ floating-point (ဒသမ ကိန်း) ကို သုညနဲ့ စားတာကို ကိုင်တွယ်ပုံ ကွာခြားချက်နဲ့ ဆိုင်ပါတယ်။

(Python မှတ်ချက်: ဒီ ထောင်ချောက်က Java မှာပဲ ရှိပါတယ်။ Python မှာ 10.0 / 0.0 က ကိန်းပြည့် အစားလိုပဲ ZeroDivisionError ကို raise (exception ဖြစ်ကြောင်း အချက်ပြ) လုပ်ပါတယ်။)

double a = 10.0;
double b = 0.0;
try {
    double result = a / b;
    System.out.println(result);
} catch (ArithmeticException e) {
    System.out.println("Cannot divide by zero!");
}

ဘာမှားနေသလဲ၊ ဘယ်လို ပြင်မလဲ။


Predict the Output (output ကို ကြိုခန့်မှန်းခြင်း)

ဒီ code က try block ရဲ့ အလယ်မှာ exception throw လုပ်တဲ့အခါ try-catch-finally block တစ်ခုလုံးထဲမှာ program run သွားပုံ (execution flow) ကို နားလည်မလည် စစ်ပါတယ်။ ဘယ် print statement တွေ ကျော်သွားလဲ၊ ဘယ်ဟာတွေ အမြဲ run လဲ သတိထားကြည့်ပါ။

ဒီ code က ဘာကို print ထုတ်မလဲ။

try {
    System.out.println("Start");
    int x = 5 / 0;
    System.out.println("After");
} catch (ArithmeticException e) {
    System.out.println("Caught");
} finally {
    System.out.println("Finally");
}
try:
    print("Start")
    x = 5 // 0
    print("After")
except ZeroDivisionError:
    print("Caught")
finally:
    print("Finally")
ရရမယ့် output: Start
Caught
Finally

Practice Exercises (လေ့ကျင့်ခန်းများ)

Core (အခြေခံ အဆင့်)

  1. စိတ်ချရတဲ့ အစား။ ကိန်းပြည့် နှစ်ခုကို ဖတ်ပါ။ try-catch ကို သုံးပြီး သုညနဲ့ စားတာကို ကိုင်တွယ်ပါ၊ program crash မဖြစ်ဘဲ error message တစ်ခုကို print ထုတ်ပါ။

  2. စိတ်ချရတဲ့ input။ Scanner ကို သုံးပြီး ကိန်းပြည့် တစ်ခုကို ဖတ်ပါ။ User က ဂဏန်း မဟုတ်တဲ့ စာသား ရိုက်ထည့်ရင် InputMismatchException ကို catch လုပ်ပြီး ဖော်ရွေတဲ့ message တစ်ခုကို print ထုတ်ပါ။

  3. finally ပါအောင်။ လေ့ကျင့်ခန်း 1 ကို ပြင်ပြီး “Calculation attempt complete.” လို့ print ထုတ်တဲ့ finally block တစ်ခု ထည့်ပါ။

Extension (တိုးချဲ့ အဆင့်)

  1. ပြန်ကြိုးစားတဲ့ loop။ User က မှန်ကန်တဲ့ ကိန်းပြည့် ရိုက်ထည့်တဲ့အထိ ဆက်မေးနေပါ။ while loop ထဲမှာ try-catch ကို သုံးပါ။ မမှန်တဲ့ input ရပြီးတိုင်း nextLine() နဲ့ buffer ကို ရှင်းဖို့ မမေ့ပါနဲ့။

  2. Array ရဲ့ အပိုင်းအခြား။ Element (အစုထဲက အချက်) 5 ခုပါတဲ့ array တစ်ခု ဖန်တီးပါ။ User ကို index တစ်ခု မေးပြီး အဲဒီ element ကို ယူသုံးကြည့်ပါ။ Index မမှန်ရင် ArrayIndexOutOfBoundsException ကို catch လုပ်ပါ။

Challenge (စိန်ခေါ်မှု အဆင့်)

  1. Error handling ပါတဲ့ calculator။ ဂဏန်း နှစ်ခုနဲ့ operator (တန်ဖိုးတွေကို တွက်ချက်တဲ့ သင်္ကေတ) တစ်ခု (+, -, *, /) ကို ဖတ်တဲ့ ရိုးရှင်းတဲ့ calculator တစ်ခု တည်ဆောက်ပါ။ မမှန်တဲ့ ဂဏန်း input၊ သုညနဲ့ စားခြင်းနဲ့ မသိတဲ့ operator တွေကို ကိုင်တွယ်ပါ၊ တစ်ခုချင်းစီအတွက် သီးခြား error message ပြပါ။

GitHub Classroom (အလိုအလျောက် စစ်ဆေးတဲ့ test တွေပါတဲ့ programming assignment များ)

Exception Handling (Java)
Practice try-catch-finally, handling InputMismatchException and ArithmeticException.

A class assignment on GitHub Classroom: use it when your teacher has set it. It needs a free GitHub account.

Working in the Codespace

  1. Accept and open. Accept the assignment above, open the link in the email from GitHub, then press Open in Codespace. In Java, change the status bar from Lightweight to Standard mode.
  2. Write and check. Open src/ExceptionHandling.java and complete each TODO. Press Run and compare the output with the comments, or run bash run-tests.sh in the Terminal.
  3. Submit. In Source Control, write a message, press Commit, then Sync Changes. Your teacher’s feedback arrives as a pull request called Feedback.

The full Codespace guide, with pictures


ဆက်စပ် ခေါင်းစဉ်များ

အရင် သိထားရမှာများ:

  • Variables & Data Types (variable နဲ့ data type များ): type တွေနဲ့ မအောင်မြင်နိုင်တဲ့ operation (လုပ်ဆောင်ချက်) တွေကို နားလည်ခြင်း
  • Selection (condition ပေါ်မူတည်ပြီး လမ်းကြောင်း ရွေးခြင်း): try-catch နဲ့ တွဲသုံးတဲ့ if/else logic

ဆက်စပ် ခေါင်းစဉ်များ:

  • Debugging: exception တွေက bug အမျိုးအစား တစ်ခုပါ၊ trace table (variable တန်ဖိုးတွေကို အဆင့်ဆင့် မှတ်တဲ့ ဇယား) တွေက အဲဒါတွေကို ရှာဖို့ ကူညီပါတယ်
  • File Processing: file I/O (file ထဲက ဖတ်ခြင်းနဲ့ file ထဲ ရေးခြင်း) မှာ exception handling ကို အများကြီး သုံးပါတယ်

နောက်ထပ် လေ့လာမယ့် ခေါင်းစဉ်များ:

  • Debugging: အမှားတွေကို ရှာပြီး ပြင်တဲ့ နည်းလမ်းများ