Monday, August 23, 2010

Errors සහ Exceptions කලමනාකරණය කිරීම (Exception Handling)

කිසියම් වැඩසටහනක් 100% ක්ම දෝශ රහිතව ලිවීම ඉතාම අසීරු කාරණයකි. වැඩසටහනේ විශාලත්වය වැඩිවත්ම මෙහි අසීරුතාව සීඝ්‍රයෙන් වැඩිවේ. Program එක සාර්ථකව compile වීම යනු එම වැඩසටහන දෝශරහිත යයි සැලකීමට සාධකයක් නොවේ. Program එකෙහි logical errors තිබිය හැක. logical errors යනු වැඩසටහන නියමාකාර ලෙස ක්‍රියානොකිරීමට(අපේක්ෂා කල පරිදි ක්‍රියා නොකිරීමට) හේතුපාදක වන කාරණයකි.

ජාවා වැඩසටහනක ඇතිවිය හැකි errors ආකාර දෙකකි.
  • Compile-time errors
  • Run-time errors
සියලුම syntax errors හෙවත් භාශාවේ කාරක රීති වලට පටහැනි අවස්ථා Compile-time errors ලෙස සැලකේ. මෙහිදී ජාවා compiler එක .java file එක මගින් .class file එක නොසාදයි. එනම් වැඩසටහන compile නොකෙරේ.

*Compile-time errors සඳහා උදාහරණ.

ඉහත වැඩසටහනේ 3 වන line එකෙහි ඇති statement එක semicolon ";" එකකින් අවසන් කර නැත එය syntax error එකකි. එමනිසා එය compile කිරීමේදී පහත දෝශය පෙන්වයි.
* Run-time errors සඳහා උදාහරණ
මෙහිදී program එක සාර්ථකව compile වුවද එය run කිරීමට යාමේදී විවිධ ගැටලු ඇතිවේ.
  • නිඛිල සංඛ්‍යා 0න් බෙදිම
  • Array එකක සීමාවෙන් පිට element එකක් access කිරීමට යාම
  • කිසියම් array එකක් තුලට නොගැලපෙන data type එකකින් යුතු අගයක් ඇතුලු කිරීම
  • null object එකක attribute හෝ methods භාවිතා කිරීම(access)
මේ සඳහා තවත් උදාහරණ රාශියක් ඇත.
දැන් අපි Run-time erors සඳහා උදාහරණ කිරිපයක් බලමු.
*Division by zero
class Runtime1{
 public static void main(String args[]){
  int a=5;
  int b=6;
  int c=10;
  int res=c/(b-a-1);
  System.out.println(res);
 }
}
මෙම වැඩසටහන සාර්ථකව compile වුවද run වීමේදී පහත දෝශය පෙන්වයි. එයට හේතුව line 6 දී (b-a-1) කොටසෙහි අගය 0 වීමයි.
* Array index out of bounds
class Runtime2{
 public static void main(String args[]){
  int arr[]=new int[5];
  int i=arr[10];
 }
}
මෙය run වීමේදී පහත දෝශය පැන නගී


දැන් අපි Run-time errors පිලිබඳ පුලුල්ව සාකච්ඡා කරමු.
Run-time errors වර්ග 2කි
  1. Errors
  2. Exceptions
අපි මුල්ම පාඩම් වලදී ඉගෙනගත්තා ජාවා තුල සියලුම දේවල් class ලෙස සලකන බව. ඒ අනුව Errors හා Exception සඳහාද ජාවා තුල class 2ක් තිබෙනවා.

Error class
මෙම ආකාරයේ errors හඳුන්වන්නේ abnormal errors හෙවත් අස්වාභාවික errors ලෙසින්. වැඩසටහනක් ලිවීමේදී අප එම වැඩසටහන තුලින් සාමාන්‍යයෙන් මෙම ආකාරයේ errors අපේක්ෂා කරන්නේ නෑ එනම් ඒවා handle කිරීමට යන්නේ නෑ.
මේ සඳහා උදාහරණ.
  • Virtual machine එකේ දෝශ
  • ThreadDeath errors

Exception class
ජාවා වැඩසටහන් තුල Error handle කරනවා යනු මෙම exceptions නියමාකාරයෙන් handle කිරීමයි. මෙහි වැදගත්කම වනුයේ run-time එකේදී කලින් අපේක්ෂා කල errors ඇතිවුවහොත් program එක terminate වීම හෝ වැරදි ප්‍රතිඵලයක් ලබාදීමෙන් වලක්වා ගැනීමයි.

බහුල වශයෙන්  හටහන්නා Exception කිහිපයකට උදාහරණ
  •  ArithmeticException
  •  ArrayIndexOutOfBoundsException
  •  IOException
  •  FileNotFoundException
  •  NumberFormatException
  •  StringOutOfBoundsException
දැන් අපි බලමු ක්‍රමලේඛයක් තුලදී Exception handle කරන්නේ කියලා.
මේ සඳහා විධි 2ක් තිබෙනවා. 

1) Throw Out (Ignore)
    මෙහිදී යම් අපේක්ෂා කල Exception එකක් හටගතහොත් එය ඉවත දැමීම නොහොත් නොසලකා හැරීම සිදුකෙරෙනවා. ඇතැම් අවස්ථා වලදී මෙම ක්‍රමය යොදාගත්තත් මෙය සුදුසුම ක්‍රමය නොවේ.
    දැන් අපි බලමු මෙම ක්‍රමය භාවිතා කරන අයුරු.
    Syntax:
        methodName throws ExceptionName{
            ..method body
        }
    උදා:
    import java.io.*;
    
    class ExceptionEx1{
     public static void main(String args[]) throws IOException{
      InputStreamReader isr=new InputStreamReader(System.in);
      BufferedReader br=new BufferedReader(isr);
      System.out.print("Enter your name : ");
      String name=br.readLine();
     }
    }
    

    2) Catch and handle
    සලකනු ලබන code segment එකක් තුල යම් අපේක්ෂිත Exception එකක් පැනනැගුනහොත් සිදුකලයුතු ක්‍රියාමාර්ගය පිලිබඳ මෙහිදී සඳහන් කෙරේ ජාවා වැඩසටහනක Exception handle කිරීම සඳහා මෙම ක්‍රමය ඉතාම සුදුසු වේ. 
    Syntax:
            try{
                ..................
                ...code segment...
                ..................
            }catch(ExceptionName1 exObj){
                ..................
                ..handling error1..
                ..................
            }
    catch(ExceptionName2 exObj){
                ..................
                ..handling error2..
                ..................
            }
    catch(ExceptionNamen exObj){
                ..................
                ..handling errorn.
                ..................
            }finally
    {
                ..................
                ..final action....
                ..................
            }

    උදා:
    import java.io.*;
    
    class ExceptionEx2{
     public static void main(String args[]) {
      int age=0;
      InputStreamReader isr=new InputStreamReader(System.in);
      BufferedReader br=new BufferedReader(isr);
      System.out.print("Enter your age : ");
      try{
       String ageStr=br.readLine(); 
       age=Integer.parseInt(ageStr);
      }catch(IOException ex1){
       System.out.println("I/O Error! "+ ex1.getMessage());
      }catch(NumberFormatException ex2){
       System.out.println("Invalid number format! "+ ex2.getMessage());
      }
     }
    }
    
    output:
    Errors catch කිරීමේදී ඒවා අපේක්ශිත අනුපිලිවෙලට සිදුකලයුතු බව මතකතබා ගත යුතුය. මෙහිදී exceptions ඇතිවිය හැකි අනුපිළිවෙල මෙන්ම class hierarchy එකද වැදගත් වේ. class hierarchy එකේ පහලින් ඇති errors මුලින් catch කර ඉහල ඇති ඒවා පසුව catch කිරීම සිදුකලයුතුය. class hierarcy එක බලාගැනීමට java documentation එක පරිශීලනය කලයුතුවේ.

    finally  block එක පිලිබඳව
    මෙතුල අන්තර්ගත කරන code segments අනිවාර්‍යයෙන්ම execute කිරීම සිදුවේ(Exception එකක් හටගත්තත් නැතත්). finally statement එක යෙදෙන අවස්ථා සඳහා උදාහරණ ලෙස open කරන ලද stream එකක් close කිරීම වැනි අවස්ථා දැක්විය හැකිය.

    Exception class එකෙහි ඇති getMessage() method එක පිලිබඳව
    මෙමගින් Exception එකට අදාල වැඩිදුර තොරතුරු String එකක් ලෙස return කරයි. 
     
    අපි දැන් බලමු අපිවිසින් අපේම(our own) Exception සාදන ආකාරය සහ ඒවා throw කරන්නේ කවර ආකාරයෙන්ද කියලා. 
    මෙහිදී මූලිකවම සිදුකරන්නේ Exception නම් predefined class එක extend කරමින් නව class එකක් සෑදීමයි.
    උදා: OwnExceptionDemo.java

    /**     
    *class  : OwnExceptionDemo     
    *Author : Kanishka Dilshan     
    *Purpose: Demonstrate howto write custom exceptions   
    *Blog   : http://javaxclass.blogspot.com     
    */ 
    
    class Printer{
     /*assumption: 
      *printing 1 page will decrease the ink level by 1
      */
     int inkLevel;//minimum=0
     int pages;
     
     public Printer(int p,int inkLevel){
      pages=p;
      this.inkLevel=inkLevel;
     }
    
     public void print(){
      try{
       if(inkLevel==0){
        throw new EmptyCartridgeException();
       }else if(pages==0){
        throw new NoPagesException();
       }else{
        pages-=1;
        inkLevel-=1;
        System.out.println("Page completed.");
       }
      }catch(EmptyCartridgeException ecEx){
       System.err.println(ecEx.getMessage());
      }catch(NoPagesException npEx){
       System.err.println(npEx.getMessage());
      }
     }
    }
    
    class NoPagesException extends Exception{
     NoPagesException(){
      super("No pages in the paper tray!");
     }
    } 
    
    class EmptyCartridgeException extends Exception{
     EmptyCartridgeException(){
      super("Cartridge is empty. Please refill it");
     }
    }
    
    class OwnExceptionDemo{
     public static void main(String args[]){
      //creating Printer object and and calling print() method
      System.out.println("---------p1 Printer object---------");
         Printer p1=new Printer(5,100);
      for(int i=0;i<8;i++) //this will cause NoPagesException
       p1.print();
    
      System.out.println("\n---------p2 Printer object---------");
      Printer p2=new Printer(5,4);
      for(int i=0;i<5;i++) //this will cause EmptyCartridgeException
       p2.print();
     }
    }
    
    මෙම වැඩසටහනෙහි output එක පහත පරිදි වේ.
    දැන් ඔබට Error handling පිලිබඳව යම් වැටහීමක් ඇතැයි සිතමි. වැඩිදුරටත් අභ්‍යාසයේ යෙදීමෙන් තවදුරටත් එය තහවුරු කරගැනීමට උත්සාහ ගන්න. ගැටලු සහගත තැන් ඇත්නම් ඒවා ඉදිරිපත් කරන්න. 
    මීලඟ පාඩමෙන් අපි Threads පිලිබඳ අධ්‍යයනය කරමු.

    Wednesday, August 11, 2010

    GUI සැකසීම සඳහා Basic Layouts යොදාගන්නා අයුරු

    අපි මෙම පාඩමෙන් සාකච්ඡා කරන්න යන්නේ ජාවා වැඩසටහන් සඳහා අතුරුමුහුනත් සැකසීමේදී components සුදුසු පරිදි ස්ථානගත කිරීම සඳහා layouts යොදාගන්නා ආකාරයයි. මෙම layouts java.awt පැකේජයේ අන්තර්ගත වනවා. අප මෙම පාඩමේදී මූලික වශයෙන් පහත දැක්වෙන layouts භාවිතා කරන අයුරු සලකා බලමු.
    • FlowLayout
    • BorderLayout
    • GridLayout
    අපි මුලින්ම බලමු ජාවා අතුරුමුහුණතකට Layout manager එකක් set කරන්නේ කොහොමද කියලා.
    syntax:
    void setLayout(LayoutManager layoutObj);
    උදා:
    this.setLayout(new FlowLayout());
    

    දැන් අපි ඉහත සඳහන් කල layouts විස්තරාත්මකව සලකා බලමු

    FlowLayout

    Panel class එකෙහි සහ එහි සියලුම child classes (උදා:Applet,JApplet,JPannel,.. ) වල default layout එක වන්නේ මෙයයි. සාමාන්‍යයෙන් components place(ස්ථානගත) කරනුයේ වමේ සිට දකුණට සහ උඩ සිට පහලට යන ආකාරයෙනි(left to right and top to bottom).
    constructor:
    FlowLayout(int align, int hgap, int vgap);
    
    align: මෙමගින් සඳහන් කරනුයේ components ස්ථානගත කරනුයේ මොන පැත්තෙන් ආරම්භ වන පරිදිද යන්නයි
    FlowLayout.LEFT
    FlowLayout.CENTER
    FlowLayout.RIGHT
    hgap, vgap : මෙමහින් සඳහන් කරනුයේ components අතර horizontal gap එක සහ vertical gap එකයි මෙය pixels වලින් ලබාදිය යුතුය.

    දැන් අපි FlowLayout එක යොදාගෙන සරල  චිත්‍රකමුහුනතක් (GUI )සකසන අයුරු බලමු.
    Code:
    import java.awt.FlowLayout;
    import javax.swing.*;
    
    public class FlowLayoutDemo extends JFrame{
    
     public FlowLayoutDemo(){
      setTitle("FlowLayoutDemo Demo");  
      JPanel myPanel=new JPanel();
      myPanel.setLayout(new FlowLayout(FlowLayout.CENTER,5,5));
      //creating JButton objects
      JButton btn1=new JButton("Component1");
      JButton btn2=new JButton("Component2");
      JButton btn3=new JButton("Component3");
      JButton btn4=new JButton("Component4");
      JButton btn5=new JButton("Component5");
      JButton btn6=new JButton("Component6");
      //adding JButton objects to the panel
      myPanel.add(btn1);
      myPanel.add(btn2);
      myPanel.add(btn3);
      myPanel.add(btn4);
      myPanel.add(btn5);
      myPanel.add(btn6);
      this.add(myPanel);
      this.setSize(492,100);
      this.setDefaultCloseOperation(3);
      this.setVisible(true);
     }
    
     public static void main(String args[]){
      new FlowLayoutDemo();
     }
    }
    

    BorderLayout

    Window සහ එහි sub class සඳහා default layout එක වේ. මෙහිදී container එක කලාප 5 කට බෙදනු ලැබේ ඒවා නම්
    1. North
    2. South
    3. East
    4. West
    5. Center
    components place කරනුයේ මෙම කලාප 5 ට වේ.
    Constructor:
    BorderLayout(int hgap, int vgap) 
    
    hgap, vgap : මෙමහින් සඳහන් කරනුයේ components අතර horizontal gap එක සහ vertical gap එකයි මෙය pixels වලින් ලබාදිය යුතුය.

    දැන් අපි BorderLayout එක යොදාගෙන සරල චිත්‍රකමුහුනතක් (GUI )සකසන අයුරු බලමු.
    Code:
    import java.awt.BorderLayout;
    import javax.swing.*;
    
    public class BorderLayoutDemo extends JFrame{
    
     public BorderLayoutDemo(){
      setTitle("BorderLayout Demo");  
      JPanel myPanel=new JPanel();
      myPanel.setLayout(new BorderLayout(5,5));
      //creating JButton objects
      JButton btn1=new JButton("North");
      JButton btn2=new JButton("East");
      JButton btn3=new JButton("South");
      JButton btn4=new JButton("West");
      JButton btn5=new JButton("Center");
      //adding JButton objects to the panel
      myPanel.add(btn1,BorderLayout.NORTH);
      myPanel.add(btn2,BorderLayout.EAST);
      myPanel.add(btn3,BorderLayout.SOUTH);
      myPanel.add(btn4,BorderLayout.WEST);
      myPanel.add(btn5,BorderLayout.CENTER);
    
      this.add(myPanel);
      this.pack();
      this.setDefaultCloseOperation(3);
      this.setVisible(true);
     }
    
     public static void main(String args[]){
      new BorderLayoutDemo();
     }
    }
    
    output:

    GridLayout

    මෙම layout එක බොහෝ දුරට FlowLayout එකට සමානය නමුත්  components place කරනුයේ සමාන cell sizes ඇති virtual grid එකක් තුලටය. මෙහිදී අදාල component එකෙහි preffered size එක නොසලකා හැරේ.

    Constructor: 
    GridLayout(int rows, int cols, int hgap, int vgap) ;
    

    rows, cols : මෙමගින් දැක්වෙන්නේ components add කරනු ලබන virtual grid එකෙහි rows සහ columns ප්‍රමාණයයි.

    hgap, vgap : මෙමහින් සඳහන් කරනුයේ components අතර horizontal gap එක සහ vertical gap එකයි මෙය pixels වලින් ලබාදිය යුතුය.
    Code:

    import java.awt.GridLayout;
    import javax.swing.*;
    
    public class GridLayoutDemo extends JFrame{
    
     public GridLayoutDemo(){
      setTitle("GridLayoutDemo Demo");  
      JPanel myPanel=new JPanel();
      myPanel.setLayout(new GridLayout(2,3,5,5));
      //creating JButton objects
      JButton btn1=new JButton("Component1");
      JButton btn2=new JButton("Component2");
      JButton btn3=new JButton("Component3");
      JButton btn4=new JButton("Component4");
      JButton btn5=new JButton("Component5");
      JButton btn6=new JButton("Component6");
      //adding JButton objects to the panel
      myPanel.add(btn1);
      myPanel.add(btn2);
      myPanel.add(btn3);
      myPanel.add(btn4);
      myPanel.add(btn5);
      myPanel.add(btn6);
    
      this.add(myPanel);
      this.pack();
      this.setDefaultCloseOperation(3);
      this.setVisible(true);
     }
    
     public static void main(String args[]){
      new GridLayoutDemo();
     }
    }
    
    output:

    අපි ඉහත සාකච්ඡා කල layout managers කිහිපය GUI සෑදීමේදී බහුල වශයෙන් යෙදේ.

    වඩාත් සංකීර්ණ GUI සෑදීම
    මෙහිදී සිදු කෙරෙනුයේ Layouts කිහිපයක් සංයුක්ත කොට කොට භාවිතා කිරීමය. Panel objects කිහිපක් සුදුසු පරිදි යෙදවීමෙන් අපට වඩාත් සංකීර්ණ GUI සකසාගත හැකිය.
    දැන් අපි Windows calculator එකෙහි අනුරුවක් අප ඉගෙනගත් LayoutManagers යොදාගෙන සෑදීමට උත්සාහ කරමු.
    Output:
    code:
    import java.awt.*;
    import javax.swing.*;
    
    public class ComplexGUIDemo extends JFrame{
    
     public ComplexGUIDemo(){
      //this.setLayout(new GridLayout(3,1));
      this.setLayout(new FlowLayout(FlowLayout.RIGHT));
      //main panels
      JPanel txtPanel=new JPanel();
      JPanel numPanel1=new JPanel();
      JPanel numPanel2=new JPanel();
      //sub panels of numPanel2
      JPanel numPanel2Sub1=new JPanel();
      JPanel numPanel2Sub2=new JPanel();
      
      JTextField textBox=new JTextField("0",33);
      textBox.setHorizontalAlignment(JTextField.RIGHT);
      txtPanel.setLayout(new GridLayout(1,1));
      txtPanel.add(textBox);
      
      numPanel1.setLayout(new FlowLayout(FlowLayout.RIGHT));
      JButton btnbacksp=new JButton("Backspace");
      JButton btnce=new JButton("CE");
      JButton btnc=new JButton("C");
      numPanel1.add(btnbacksp);
      numPanel1.add(btnce);
      numPanel1.add(btnc);
      
      numPanel2Sub1.setLayout(new GridLayout(4,1,5,5));
      JButton btnMC=new JButton("MC");
      JButton btnMR=new JButton("MR");
      JButton btnMS=new JButton("MS");
      JButton btnMPl=new JButton("M+");
      numPanel2Sub1.add(btnMC);
      numPanel2Sub1.add(btnMR);
      numPanel2Sub1.add(btnMS);
      numPanel2Sub1.add(btnMPl);
      
      numPanel2Sub2.setLayout(new GridLayout(4,5,5,5));
      JButton btn7=new JButton("7");
      JButton btn8=new JButton("8");
      JButton btn9=new JButton("9");
      
      JButton btndv=new JButton("/");
      JButton btnsqrt=new JButton("sqrt");
      numPanel2Sub2.add(btn7);
      numPanel2Sub2.add(btn8);
      numPanel2Sub2.add(btn9);
      numPanel2Sub2.add(btndv);
      numPanel2Sub2.add(btnsqrt);
      
      JButton btn4=new JButton("4");
      JButton btn5=new JButton("5");
      JButton btn6=new JButton("6");
      
      JButton btnmul=new JButton("*");
      JButton btnperc=new JButton("%");
      numPanel2Sub2.add(btn4);
      numPanel2Sub2.add(btn5);
      numPanel2Sub2.add(btn6);
      numPanel2Sub2.add(btnmul);
      numPanel2Sub2.add(btnperc);
      
      JButton btn1=new JButton("1");
      JButton btn2=new JButton("2");
      JButton btn3=new JButton("3");
      
      JButton btnmin=new JButton("-");
      JButton btn1bx=new JButton("1/x");
      numPanel2Sub2.add(btn1);
      numPanel2Sub2.add(btn2);
      numPanel2Sub2.add(btn3);
      numPanel2Sub2.add(btnmin);
      numPanel2Sub2.add(btn1bx);
      
      JButton btn0=new JButton("0");
      JButton btnPM=new JButton("+/-");
      JButton btnpt=new JButton(".");
      
      JButton btnpl=new JButton("+");
      JButton btneq=new JButton("=");
      numPanel2Sub2.add(btn0);
      numPanel2Sub2.add(btnPM);
      numPanel2Sub2.add(btnpt);
      numPanel2Sub2.add(btnpl);
      numPanel2Sub2.add(btneq);
      
      numPanel2.setLayout(new FlowLayout());
      numPanel2.add(numPanel2Sub1);
      numPanel2.add(numPanel2Sub2);
      
      this.add(txtPanel);
      this.add(numPanel1);
      this.add(numPanel2);
      
      this.setTitle("My Calculator");
      this.setDefaultCloseOperation(3);
      this.setVisible(true);
      this.setSize(390,235);
     }
    
     public static void main(String args[]){
      new ComplexGUIDemo();
     }
    }
    
    GUI සම්බන්ද තවත් කරුණු අපි ඉදිරි පාඩම්වලදී සාකච්ඡා කරමු.
    මෙම පාඩමට සම්බන්ද source codes බාගත කරගැනීම සඳහා සඳහා පහත ලින්ක් එක භාවිතා කරන්න.