February 15, 2017

I/O Streams

အရင်တစ်ခေါက် File အကြောင်းရေးသားခဲ့စဉ်က File တွေ Directory တွေကို Create လုပ်နိုင်တယ်။ ပြီးတော့လဲ Delete လုပ်နိုင်တယ်။ အမည်ပြောင်းတာတို့လဲ လုပ်နိုင်ခဲ့ပါတယ်။ ဒါပေမဲ့ အဲ့ဒီ File တွေထဲက Data တွေကို Read လုပ်တာတို့ Write လုပ်တာတို့ကို မလုပ်နိုင်ခဲ့ပါဘူး။

File ထဲက Data တွေကို Input Output လုပ်နိုင်ဖို့အတွက် I/O Stream တွေကို အသုံးပြုရမှာ ဖြစ်ပါတယ်။ Java Language မှာ I/O Stream တွေကို အသုံးပြုမည့် Data Type အပေါ်မူတည်ပြီး အမျိုးမျိုးပြင်ဆင်ထားပါတယ်။ ပြီးတော့ I/O Stream တွေကို ရေးသားတဲ့နေရာမှာလဲ Design Pattern တွေကို အသုံးပြုရေးသားထားပါတယ်။ အရင်ဆုံး I/O Stream တွေကို လေ့လာတဲ့နေရာမှာ အသုံးပြုနိုင်တဲ့ I/O Stream တွေနဲ့ အသုံးပြုပုံတွေကို လေ့လာပြီး၊ နောက်ပိုင်းမှ I/O Stream တွေမှာ အသုံးပြုထားတဲ့ Design Patterns တွေကို လေ့လာသွားပါမယ်။


What are Streams?

Stream တွေဟာ Java Program ထဲမှာအသုံးပြုမည့် Input Source တွေနဲ့ Output Destination တွေကိုကိုယ်စားပြုတဲ့ Interface Object တွေဖြစ်ကြပါတယ်။ Source တွေကော Destination တွေပါ ပုံစံအမျိုးမျိုးရှိနိုင်ကြပြီး Input Output လုပ်ကြမည့် Data တွေလဲ​အမျိုးမျိုးဖြစ်နိုင်ပါတယ်။

Input Source လိုပြောတဲ့နေရာမှာ File တစ်ခုလဲဖြစ်နိုင်သလို System Console ကလာတဲ့ Input လဲ ဖြစ်နေနိုင်ပါတယ်။ ဒါမှမဟုတ် အခြားသော Program တစ်ခုခုလဲ ဖြစ်နိုင်ပါတယ်။ ဒီလိုပဲ Output Destination လို့ပြောတဲ့နေရာမှာလဲ File တစ်ခုခု၊ System Console ဒါမှမဟုတ် အခြားသော Program တစ်ခုခုလဲ ဖြစ်နေနိုင်ပါတယ်။ ဒါပေမဲ့ အခြေခံအားဖြင့်တော့ I/O Stream တွေကို Input Stream တွေနဲ့ Output Streams တွေဆိုပြီး သတ်မှတ်ထားပါတယ်။


Input Streams


Java Program ထဲကအသုံးပြုရန် Data များအား Source တစ်နေရာရာမှ ဖတ်ယူနိုင်ဖို့အတွက် Input Stream များကို အသုံးပြုရပါတယ်။ အသုံးပြုလိုတဲ့ Data Type အပေါ်မူတည်ပြီး Streams အမျိုးမျိုးကိုလဲ ပြင်ဆင်ထားပါတယ်။ အသုံးပြုနိုင်တဲ့ Data Type တွေကတော့ bytes, primitive type data, localize character များနဲ့ Object တွေပဲ ဖြစ်ကြပါတယ်။


Output Streams


Java Program ထဲကနေ Destination တစ်ခုဆီကို Data များကို Output လုပ်ချင်တဲ့အခါ Output Stream တွေကို အသုံးပြုနိုင်ပါတယ်။ Destination အနေနဲ့ File တစ်ခုခုဖြစ်နိုင်သလို၊ System Console လဲ ဖြစ်နိုင်သလို အခြားသော Program တစ်ခုခုလဲ ဖြစ်နိုင်ပါတယ်။ ပြီးတော့ byte အနေနဲ့သော်၎င်း၊ primitive data type အနေနဲ့သော်၎င်း၊ localize character များအနေနဲ့သော်၎င်း၊ Object များအနေနဲ့သော်၎င်း Outputလုပ်နိုင်ပါတယ်။

Input Stream တုန်းကလိုပဲ အသုံးပြုလိုတဲ့ Data Type တွေအလိုက် Stream တွေကို ရွေးချယ် အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။


Data Types and Streams


Java IO ရဲ့ Stream Class တွေအားလုံးဟာ InputStream နဲ့ OutputStream Class တွေကနေ ဆင်းသက်လာကြတဲ့ Class တွေဖြစ်ပါတယ်။ Input Output အနေနဲ့ အသုံးပြုလိုတဲ့ Data Type အလိုက် Stream တွေကို ခွဲခြားအသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။

Data Types Input Streams Output Streams
Byte FileInputStream FileOutputStream
Characters FileReader FileWriter
String Line BufferedReader PrintWriter
Primitive Data DataInputStream DataOutputStream
Objects ObjectInputStream ObjectOutputStream


Byte Streams


File တစ်ခုထဲက Data တွေကို Binary Data တွေဖြစ်တဲ့ 8-bit bytes ပုံစံနဲ့ Read Write လုပ်လိုတဲ့အခါ Byte Streams တွေကို အသုံးပြုရမှာ ဖြစ်ပါတယ်။ Byte Stream တွေအားလုံးဟာ InputStream နဲ့ OutputStream Class တွေရဲ့ Sub Class တွေဖြစ်ကြပြီး အသုံးများတာကတော့ FileInputStream နဲ့ FileOutputStream Class တို့ပဲ ဖြစ်ကြပါတယ်။

FileInputStream ကတော့ File တစ်ခုကနေ Byte တွေကို Read လုပ်ချင်တဲ့အခါမှာ အသုံးပြုနိုင်တဲ့ Stream တစ်ခုဖြစ်ပြီး၊ FileInputStream Object ကို တည်ဆောက်ရန် Constructor ၃ မျိုးပြင်ဆင်ထားပါတယ်။

Constructor Description
FileInputStream(File file) Input လုပ်ရမည့် File ကို ကိုယ်စားပြုတဲ့ File Object ကို Argument အနေနဲ့ အသုံးပြုရပါမယ်
FileInputStream(FileDescription fdObj) Input လုပ်မည့် File ကို ဖေါ်ပြပေးနိုင်တဲ့ FileDescriptor Object ကို Argument အနေနဲ့ အသုံးပြုရပါမယ်
FileInputStream(String name) Input လုပ်မည့် File ရဲ့ အမည် String Object ကို Argument အနေနဲ့ အသုံးပြုရပါမယ်

FileInputStream Object ကနေ byte တွေကို 1 byte ချင်း Read လုပ်လိုတဲ့အခါ read() ဆိုတဲ့ Method ကို အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။

FileOutputStream ကတော့ File တစ်ခုဆီကို Byte တွေ အနေနဲ့ Output လုပ်ပေးနိုင်တဲ့ Stream Object တစ်ခု ဖြစ်ပါတယ်။ FileOutputStream Object ကို တည်ဆောက်ဖို့အတွက် ပြင်ဆင်ထားတဲ့ Constructor တွေကတော့ အောက်ပါ အတိုင်းဖြစ်ကြပါတယ်။

Constructor Description
FileOutputStream(File file) Output လုပ်ရမည့် File ကို ကိုယ်စားပြုတဲ့ File Object ကို Argument အနေနဲ့ အသုံးပြုရပါမယ်
FileOutputStream(File file, boolean append) Output လုပ်ရမည့် File ကို ကိုယ်စားပြုတဲ့ File Object နဲ့ boolean တန်ဖိုးတစ်ခုကို Argument အနေနဲ့ ပေးရပါမယ်။
boolean ရဲ့ တန်ဖိုးဟာ true ဖြစ်မယ်ဆိုရင် လက်ရှိရှိပြီးသား File မှာ Output လုပ်လာတဲ့ Data တွေကို ဆက်ပြီးထည့်ပေးနိုင်မှာ ဖြစ်ပါတယ်
FileOutputStream(FileDescription fdObj) Output လုပ်မည့် File ကို ဖေါ်ပြပေးနိုင်တဲ့ FileDescriptor Object ကို Argument အနေနဲ့ အသုံးပြုရပါမယ်
FileOutputStream(String name) Output လုပ်မည့် File ရဲ့ အမည် String Object ကို Argument အနေနဲ့ အသုံးပြုရပါမယ်
FileOutputStream(String name, boolean append) Output လုပ်မည့် File ရဲ့ အမည်ကို String Object နဲ့ boolean တန်ဖိုးတစ်ခုကို Argument အနေနဲ့ ပေးရပါမယ်။
boolean ရဲ့ တန်ဖိုးဟာ true ဖြစ်မယ်ဆိုရင် လက်ရှိရှိပြီးသား File မှာ Output လုပ်လာတဲ့ Data တွေကို ဆက်ပြီးထည့်ပေးနိုင်မှာ ဖြစ်ပါတယ်

Output လုပ်လိုတဲ့ Byte Data တွေကို ရေးသားနိုင်ဖို့အတွက် write(int b), write(byte [] b) နဲ့ write(byte [] b, int off, int len) method တို့ကို ပြင်ဆင်ထားပါတယ်။ 1 byte ချင်း Write လုပ်ချင်ရင်တော့ write(int b) ကို အသုံးပြုရမှာ ဖြစ်ပါတယ်။

Stream Object တွေဟာ Resource တွေကို အသုံးပြုနေတဲ့ Object အမျိုးအစား ဖြစ်တဲ့အတွက် အသုံးပြုပြီးတဲ့အခါမှာ ပြန်ပြီး ပိတ်ပေးဖို့လိုအပ်တဲ့အတွက် close() ဆိုတဲ့ Method ကိုလဲ ပြင်ဆင်ပေးထားပါတယ်။ ဒါပေမဲ့ Java SE 7 ရဲ့ ရေးသားပုံအသစ်ဖြစ်တဲ့ try-with-resource ရေးသားပုံနဲ့ ရေးသားမယ်ဆိုရင်တော့ အလိုအလျောက် ပိတ်ပေးနိုင်မှာ ဖြစ်ပါတယ်။
package com.jdc.io.stream.ep1;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyByte {

    public static void main(String[] args) {
        
        try (FileInputStream in = new FileInputStream("from.txt");
                FileOutputStream out = new FileOutputStream("to.txt")){
            
            int i = 0;
            
            while((i = in.read()) != -1) {
                out.write(i);
            }
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

အထက်ပါနမူနာကတော့ from.txt ဆိုတဲ့ File ထဲမှာရှိတဲ့ Data တွေကို 1 byte ချင်း read လုပ်ပြီး to.txt ဆိုတဲ့ဖိုင်ထဲကို 1 byte ချင်း write လုပ်နေတဲ့ နမူနာဖြစ်ပါတယ်။

FileInputStream နဲ့ FileOutputStream Object တွေကို try with resource နဲ့ ရေးသားထားတဲ့အတွက် နောက်ဆုံးမှာ အလိုအလျောက်ပိတ်ပေးသွားမှာ ဖြစ်တယ်။ အဲ့ဒီအတွက် တကူးတက close လုပ်ပေးစရာမလိုတော့ ပါဘူး။ တဖန် while clause ထဲမှာ i = in.read() ဆိုပြီး FileInputStream ကနေ 1 byte ချင်း Read လုပ်နေပါတယ်။ နောက်ဆုံး Read လုပ်စရာမရှိတော့တဲ့အခါ -1 ကို Return ပြန်မှာ ဖြစ်ပြီး While loop ထဲကနေ ထွက်သွားမှာ ဖြစ်ပါတယ်။

While Loop ထဲမှာတော့ Read လုပ်လာတဲ့ တန်ဖိုးကို 1 byte ချင်း FileOutputStream ကို သုံးပြီး write လုပ်ပေးနေပါတယ်။ ဤနည်းအားဖြင့် from.txt ဖိုင်ထဲက Data တွေကို to.txt ဖိုင်ထဲကို 1 byte ချင်း Write လုပ်ပေးသွားနိုင်မှာ ဖြစ်ပါတယ်။


Character Streams

Text File တစ်ခုအတွင်းရှိ Data များကို Character ပုံစံနဲ့ Read / Write လုပ်ချင်ရင် Character Streams များကို အသုံးပြုရမှာ ဖြစ်ပါတယ်။ Character Streams တွေဟာ InputStreamReader နဲ့ OutputStreamWriter တို့ရဲ့ Sub Class တွေ ဖြစ်ကြပြီး FileReader နဲ့ FileWriter တို့ဟာ အသုံးများပါတယ်။

FileReader နဲ့ FileWriter တို့ဟာ Default Encoding နဲ့ Character တွေကို အလွယ်တကူ Read / Write လုပ်နိုင်အောင်ပြင်ဆင်ထားတဲ့ Class တွေဖြစ်ကြပြီး၊ Character Set တို့ကို ကိုယ်တိုင် သတ်မှတ်ပြီး Read / Write လုပ်ချင်ရင်တော့ InputStreamReader နဲ့ OutputStreamWriter တို့ကို အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။

FileReader ကို Character များကို Read လုပ်တဲ့နေရာမှာ အသုံးပြုပြီး ရေးသားနိုင်တဲ့ Constructor များကတော့ အောက်ပါ အတိုင်းဖြစ်ကြပါတယ်။

Constructor Description
FileReader(File file) Input လုပ်ရမည့် File ကို ကိုယ်စားပြုတဲ့ File Object ကို Argument အနေနဲ့ အသုံးပြုရပါမယ်
FileReader(FileDescription fdObj) Input လုပ်မည့် File ကို ဖေါ်ပြပေးနိုင်တဲ့ FileDescriptor Object ကို Argument အနေနဲ့ အသုံးပြုရပါမယ်
FileReader(String name) Input လုပ်မည့် File ရဲ့ အမည် String Object ကို Argument အနေနဲ့ အသုံးပြုရပါမယ်

FileWriter ကို Character များကို Write လုပ်တဲ့နေရာမှာ အသုံးပြုပြီး ရေးသားနိုင်တဲ့ Constructor များကတော့ အောက်ပါ အတိုင်းဖြစ်ကြပါတယ်။

Constructor Description
FileWriter(File file) Output လုပ်ရမည့် File ကို ကိုယ်စားပြုတဲ့ File Object ကို Argument အနေနဲ့ အသုံးပြုရပါမယ်
FileWriter(File file, boolean append) Output လုပ်ရမည့် File ကို ကိုယ်စားပြုတဲ့ File Object နဲ့ boolean တန်ဖိုးတစ်ခုကို Argument အနေနဲ့ ပေးရပါမယ်။
boolean ရဲ့ တန်ဖိုးဟာ true ဖြစ်မယ်ဆိုရင် လက်ရှိရှိပြီးသား File မှာ Output လုပ်လာတဲ့ Data တွေကို ဆက်ပြီးထည့်ပေးနိုင်မှာ ဖြစ်ပါတယ်
FileWriter(FileDescription fdObj) Output လုပ်မည့် File ကို ဖေါ်ပြပေးနိုင်တဲ့ FileDescriptor Object ကို Argument အနေနဲ့ အသုံးပြုရပါမယ်
FileWriter(String name) Output လုပ်မည့် File ရဲ့ အမည် String Object ကို Argument အနေနဲ့ အသုံးပြုရပါမယ်
FileWriter(String name, boolean append) Output လုပ်မည့် File ရဲ့ အမည်ကို String Object နဲ့ boolean တန်ဖိုးတစ်ခုကို Argument အနေနဲ့ ပေးရပါမယ်။
boolean ရဲ့ တန်ဖိုးဟာ true ဖြစ်မယ်ဆိုရင် လက်ရှိရှိပြီးသား File မှာ Output လုပ်လာတဲ့ Data တွေကို ဆက်ပြီးထည့်ပေးနိုင်မှာ ဖြစ်ပါတယ်
FileReader နဲ့ FileWriter တို့ရဲ့ အသုံးပြုပုံဟာ အခြေခံအားဖြင့် FileInputStream နဲ့ FileOutputStream တို့နဲ့အတူတူပဲ ဖြစ်ပါတယ်။
package com.jdc.io.stream.ep2;

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyChar {
    
    public static void main(String[] args) {
        
        try(FileReader in = new FileReader("from.txt");
                FileWriter out = new FileWriter("out.txt")) {
            
            int c = 0;
            
            while((c = in.read()) != -1) {
                out.write(c);
            }
            
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }
}

FileReader ကို အသုံးပြုပြီး Text File အတွင်းမှ Character များကို Read လုပ်ရာမှာ read() method ကို အသုံးပြုနိုင်မှာဖြစ်ပါတယ်။ Return Type မှာ int ဖြစ်ပြီး Character တစ်လုံးကို ကိုယ်စားပြုမှာ ဖြစ်ပါတယ်။ နောက်ဆုံး Read လုပ်စရာမရှိတော့တဲ့အခါ -1 ကို Return ပြန်မှာဖြစ်ပါတယ်။

Character စာလုံးများကို Write လုပ်လိုတဲ့အခါ FileWriter Object ရဲ့ write(int char) method ကို အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။ Write Method ကို အသုံးပြုပြီး Character တစ်လုံးချင်းစီကို Output လုပ်ပေးနိုင်မှာ ဖြစ်ပါတယ်။

အထက်ပါနမူနာထဲံမှာတော့ from.txt file ထဲမှ Character များကို while statement ဖြင့် တစ်လုံးစီဖတ်ပြီး out.txt file ထဲကို Character တစ်လုံးစီ Output လုပ်ပေးနိုင်မှာ ဖြစ်ပါတယ်။


Line Oriented IO


Character I/O ကို အသုံးပြုတဲ့အခါမှာ Character တစ်လုံးခြင်း Read / Write လုပ်တာထက် ဒီထက်ပိုပြီး ကြီးမားတဲ့ Unit နဲ့ Read / Write လုပ်လေ့ရှိပါတယ်။ အသုံးများတာက စာကြောင်း တစ်ကြောင်းစီကို Read / Write လုပ်တဲ့ပုံစံပဲ ဖြစ်ပါတယ်။ Line တစ်ခုချင်းစီကို Read / Write လုပ်ဖို့အတွက် BufferedReader, BufferedWriter နဲ့ PrintWriter တို့ကို အသုံးပြုနိုင်ပါတယ်။


BufferedReader

BufferedReader တွေဟာ Text File တွေကနေ Character တွေကို သတ်မှတ်ထားတဲ့ Buffered Size အလိုက် Character Array အဖြစ်သော်၎င်း၊ စာကြောင်းတစ်ကြောင်းစီလိုက်သော်၎င်း Read လုပ်နိုင်အောင်ပြင်ဆင်ထားတဲ့ Class တွေ ဖြစ်ပါတယ်။

BufferedReader Class ကို Object ဆောက်နိုင်တဲ့ Constructor တွေကတော့ အောက်ပါ အတိုင်းဖြစ်ပါတယ်။

Constructor Description
BufferedReader(Reader in) Reader Object တစ်ခုကို Argument အနေနဲ့ပေးရပါမယ်။​ Buffer Size ကိုတော့ Default Size အတိုင်း အသုံးပြုသွားမှာ ဖြစ်ပါတယ်။
BufferedReader(Reader in, int size) Reader Object တစ်ခုနဲ့ Buffer Size ကို Argument အနေနဲ့ ပေးပြီး BufferedReader Object တစ်ခုကို တည်ဆောက်နိုင်မှာ ဖြစ်ပါတယ်။ Buffer Size ကို သတ်မှတ်ပြီး အသုံးပြုလိုပါက ဤ Constructor ကို အသုံးပြုရမှာ ဖြစ်ပါတယ်။

package com.jdc.io.stream.ep3;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class LineReader {
    
    public static void main(String[] args) {
        
        try(BufferedReader in = new BufferedReader(new FileReader("line.txt"))) {
            
            String line = null;
            
            while((line = in.readLine()) != null) {
                System.out.println(line);
            }
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

BufferedReader ကနေ စာကြောင်း တစ်ကြောင်းစီ Read လုပ်လိုပါက readLine() method ကို အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။ အထက်ပါ နမူနာမှာတော့ in.readLine() ကို အသုံးပြုပြီး line variable မှာ အစားထိုးနေပါတယ်။ ပြီးတော့ While Statement မှာ line ဟာ null မဖြစ်မခြင်း loop ပတ်နေမှာ ဖြစ်ပြီး စာကြောင်းတွေ ဖတ်စရာကုန်သွားရင် null ကို Return လုပ်မှာ ဖြစ်တဲ့အတွက် looping ထဲကနေ ထွက်သွားပါလိမ့်မယ်။

ဒါ့ကြောင့် line.txt ထဲက စာကြောင်းတွေကို အစ စာကြောင်းကနေ တစ်ကြောင်းချင်း ကုန်သွားသည် အထိ Read လုပ်သွားနိုင်မှာ ဖြစ်ပါတယ်။


PrintWriter


Java Program ထဲကနေ Character တွေကို String အနေနဲ့ Write လုပ်လိုတဲ့အခါမှာ PrintWriter ကို အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။ PrintWriter ကို အသုံးပြုပြီး String တွေလို ဒီအတိုင်း Write လုပ်နိုင်သလို၊ Format ချပြီးလဲ Write လုပ်နိုင်ပါတယ်။ ထို့အပြင် Locale အလိုက်သတ်မှတ်ပြီးလဲ Format လုပ်နိုင်မှာ ဖြစ်ပါတယ်။ PrintWriter Object ကို တည်ဆောက်နိုင်တဲ့ Constructor တွေကတော့ အောက်ပါ အတိုင်းဖြစ်ကြပါတယ်။

Constructor Description
PrintWriter(File file) Output File ကို သတ်မှတ်ပြီး PrintWriter Object ကို တည်ဆောက်နိုင်မှာ ဖြစ်ပါတယ်။ Auto Flush ကိုတော့ လုပ်ပေးနိုင်မှာ မဟုတ်ပါဘူး
PrintWriter(File file, String csn) Output File နဲ့ Character Set ကို သတ်မှတ်ပြီး PrintWriter Object ကို တည်ဆောက်နိုင်မှာ ဖြစ်ပါတယ်။ Auto Flush ကိုတော့ လုပ်ပေးနိုင်မှာ မဟုတ်ပါဘူး
PrintWriter(OutputStream out) OutputStream ကို သတ်မှတ်ပြီး PrintWriter Object ကို တည်ဆောက်နိုင်မှာ ဖြစ်ပါတယ်။ Auto Flush ကိုတော့ လုပ်ပေးနိုင်မှာ မဟုတ်ပါဘူး
PrintWriter(OutputStream out, boolean autoFlush) OutputStream နဲ့ Auto Flush Mode ကို သတ်မှတ်ပြီး PrintWriter Object ကို တည်ဆောက်နိုင်မှာ ဖြစ်ပါတယ်။
PrintWriter(String fileName) File Name ကို သတ်မှတ်ပြီး PrintWriter Object ကို တည်ဆောက်နိုင်မှာ ဖြစ်ပါတယ်။ Auto Flush ကိုတော့ လုပ်ပေးနိုင်မှာ မဟုတ်ပါဘူး
PrintWriter(String fileName, String csn) File Name နဲ့ Character Set ကို သတ်မှတ်ပြီး PrintWriter Object ကို တည်ဆောက်နိုင်မှာ ဖြစ်ပါတယ်။ Auto Flush ကိုတော့ လုပ်ပေးနိုင်မှာ မဟုတ်ပါဘူး
PrintWriter(Writer out) Writer ကို သတ်မှတ်ပြီး PrintWriter Object ကို တည်ဆောက်နိုင်မှာ ဖြစ်ပါတယ်။ Auto Flush ကိုတော့ လုပ်ပေးနိုင်မှာ မဟုတ်ပါဘူး
PrintWriter(Writer out, boolean autoFlush) Writer နဲ့ Auto Flush Mode ကို သတ်မှတ်ပြီး PrintWriter Object ကို တည်ဆောက်နိုင်မှာ ဖြစ်ပါတယ်။

package com.jdc.io.stream.ep3;

import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class LineWriter {

    private static final String [] ARRAY = {
            "Hello Java",
            "Hello Java IO",
            "Learn java Programming."
    };
    
    public static void main(String[] args) {
        
        try(PrintWriter out = new PrintWriter(new FileWriter("line.txt"))) {
            
            for (String line : ARRAY) {
                out.println(line);
            }
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

String တွေကို Write လုပ်ဖို့အတွက် print(String str) ဒါမှမဟုတ် write(String str) ကို အသုံးပြုနိုင်ပါတယ်။ ဒါအပြင် Line တွေကို Write လုပ်ဖို့အတွက် println(String str) ကို အသုံးပြုနိုင်ပါတယ်။ Format လုပ်ချင်ရင်တော့ printf(String format, String … param) ကို အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။


Data Streams

Primitive Data နဲ့ String တန်ဖိုး တွေကို Read / Write လုပ်ချင်တဲ့အခါ DataInputStream နဲ့  DataOutputStream တို့ကို အသုံးပြုနိုင်ပါတယ်။

Constructor Description
DataOutputStream(OutputStream out) OutputStream Object တစ်ခုကို အသုံးပြုပြီး DataOutputStream ကို တည်ဆောက်ရန် ပြင်ဆင်ထားတဲ့ Constructor ဖြစ်ပါတယ်။
DataInputStream(InputStream in) InputStream Object တစ်ခုကို အသုံးပြုပြီး DataInputStream ကို တည်ဆောက်ရန် ပြင်ဆင်ထားတဲ့ Constructor ဖြစ်ပါတယ်။

အသုံးပြုလိုတဲ့ Data Type အလိုက် Method တွေကိုလဲ ခွဲခြားပြင်ဆင်ထားပါတယ်။

Data Type DataInputStream DataOutputStream
boolean readBoolean() writeBoolean(boolean v)
char readChar() writeChar(int v)
byte readByte() writeByte(int v)
short readShort() writeShort(int v)
int readInt() writeInt(int v)
long readLong() writeLong(long v)
float readFloat() writeFloat(float v)
double readDouble() writeDouble(doble v)
String readUTF() writeUTF(String str)

မိမိအသုံးပြုလိုတဲ့  Data Type အလိုက် သက်ဆိုင်ရာ Method ကို အသုံးပြုပြီး ရေးသားရမှာ ဖြစ်ပါတယ်။


Write Data

package com.jdc.io.stream.ep4;

import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class DataOutput {
    
    private static final String name = "Aung Aung";
    private static final int age = 20;
    private static final boolean isMan = true;
    
    public static void main(String[] args) {
        
        System.out.println("Starting Output");

        try(DataOutputStream out = new DataOutputStream(new FileOutputStream("data.dat"))) {
            
            out.writeUTF(name);
            out.writeInt(age);
            out.writeBoolean(isMan);
            
            System.out.println("End Output");
        } catch (IOException e) {
            System.out.println("Output Error");
        }
        
    }

}

အထက်ပါနမူနာမှာတော့ name variable ဟာ String ဖြစ်တဲ့အတွက် writeUTF ကို အသုံးပြုပြီး၊ age ဟာ int ဖြစ်တဲ့အတွက် writeInt ကို အသုံးပြုပါတယ်။ တဖန် isMan ဆိုတဲ့ Variable ဟာ boolean type ဖြစ်တဲ့အတွက် writeBoolean ကို အသုံးပြရမှာ ဖြစ်ပါတယ်။


Reading Data

package com.jdc.io.stream.ep4;

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;

public class DataInput {

    public static void main(String[] args) {
        
        try(DataInputStream in = new DataInputStream(
                new FileInputStream("data.dat"))) {
            
            System.out.println("Name : " + in.readUTF());
            System.out.println("Age  : " + in.readInt());
            System.out.println("Male : " + in.readBoolean());
            
        } catch (IOException e) {
            e.printStackTrace();
        }
        
    }
}

အထက်ပါ နမူနာကတော့ DataOutput ဖြင့် Write လုပ်ထားတဲ့ data.dat file ထဲက Data တွေကို ပြန်ပြီး Read လုပ်နေတာဖြစ်ပါတယ်။ String Data တွေကို readUTF ကိုအသုံးပြုပြီး၊ int ကိုတော့ readInt ကို အသုံးပြုပါတယ်။ တဖန် boolean ကိုတော့ readBoolean method ကို အသုံးပြုပါတယ်။


Serialization

အရှေ့တွင်ဖေါ်ပြခဲ့သလို Java ဘာသာရပ်တွင် Byte, Character, Primitive Data များနှင့် String များကို Read / Write လုပ်နိုင်တဲ့အပြင် Object တွေကိုလဲ Object အတိုင်း Read / Write လုပ်နိုင်ပါတယ်။

Java ဘာသာရပ်မှာ JVM Memory အပေါ်မှာရှိတဲ့ Object တွေကို အခြား တစ်နေနေရာကို ပို့ပေးလိုက်ခြင်းကို Serialize လုပ်တယ်လို့ခေါ်ပါတယ်။ တဖန် တစ်ခြားတစ်နေနေရာကနေလာတဲ့ Serialized လုပ်ထားတဲ့ Data တွေကနေ JVM Memory အပေါ်ကို ပြန်ပြီး Object အဖြစ်ပြန်ပြောင်းတာကိုတော့ Deserialize လုပ်တယ်လို့ခေါ်ပါတယ်။ Deseiralize လုပ်တယ်ဆိုတာကလဲ Serialize လုပ်ထားတဲ့ Data များကိုသာ ပြုလုပ်နိုင်မှာ ဖြစ်ပါတယ်။

နမူနာအားဖြင့် Program ထဲမှာ သုံးနေတဲ့ Java Object တွေကို File တစ်ခုခုမှာ သွားသိမ်းတာတို့၊ Internet ကိုဖြတ်ပြီး တစ်ခြားတစ်နေနေရာကိုပို့ပေးတာတို့ဟာ Serialize လုပ်တာဖြစ်ကြပါတယ်။ Server အပေါ်မှာရှိတဲ့ Object တွေကို Session ပေါ်မှာ သုံးနေတယ်ဆိုတာကလဲ Serialize လုပ်နေတာပဲ ဖြစ်ပါတယ်။

ဒါဖြင့် ဘယ်လို Object တွေကို Serialize လုပ်လို့ရတာလဲ။ Primitive Data Type တွေ၊ Serializable Interface ကို Implement လုပ်ထားတဲ့ Object တွေနဲ့ Serializable Object တွေရဲ့ Collection တွေ ဆိုရင် Serialize လုပ်လို့ရမှာ ဖြစ်ပါတယ်။

Object တစ်ခုကို Serialize လုပ်တဲ့အခါမှာ Object ရဲ့ State တွေဖြစ်ကြတဲ့ Instance Variable တွေကိုသာ Serialize လုပ်သွားမှာ ဖြစ်ပါတယ်။ ဒါ့ကြောင့် Serialize လုပ်မည့် Object ရဲ့ Instance Variable တွေဟာလဲ Serializable ဖြစ်ဖို့လိုအပ်ပါတယ်။ တကယ်လို့ Serialize မလုပ်ချင်တဲ့ Instance Variable တွေဆိုရင် transient modifier ကို ရေးသားပြီး ဖေါ်ပြနိုင်ပါတယ်။ Instance Variable တွေရှေ့မှာ transient ကို ရေးသားထားရင် အဲ့ဒီ Field ကို Serialize လုပ်မှာ မဟုတ်တော့ပါဘူး။
package com.jdc.io.stream.ep5;

import java.io.Serializable;

public class Employee implements Serializable{

    private static final long serialVersionUID = 1L;

    private int id;
    private String name;
    private String phone;
  
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPhone() {
        return phone;
    }
    public void setPhone(String phone) {
        this.phone = phone;
    }
}


Serial Version UID

Serializable Object တစ်ခုကို Serialize လုပ်ပြီး ပြန်ပြီး Deserialize လုပ်တဲ့အခါ Serial Version UID ကို အသုံးပြုပြီး Class ရဲ့ Version မှန်မမှန်ကို ပြန်ပြီး စစ်ဆေးလေ့ရှိပါတယ်။ Serial Version UID ကို ရေးသားရာမှာ static final long serialVersionUID ဆိုတဲ့ပုံစံနဲ့ ရေးသားပေးရပါတယ်။ Access Modifier ကိုတော့ နှစ်သက်ရာ ရေးသားအသုံးပြုနိုင်ပါတယ်။

Serialize လုပ်တဲ့အခါမှာ Serial Version UID ဟာ Static Variable ဖြစ်ပေမဲ့ ခြွင်းချက်အနေနဲ့ Serialize အလုပ်ခံရမှာ ဖြစ်ပါတယ်။ Deserialize လုပ်တဲ့အခါမှာ လက်ရှိ Class နဲ့ Deserialize လုပ်မည့် Object ရဲ့ Serial Version UID ကို တိုက်စစ်ပြီး မှန်ကန်မှသာ Serialize လုပ်ပေးမှာ ဖြစ်ပါတယ်။ တကယ်လို့ Version နှစ်ခုမတူညီခဲ့ပါက InvalidClassException ကို ဖြစ်ပေါ်စေမှာ ဖြစ်ပါတယ်။

တကယ်လို့ Serializable Class တစ်ခုမှာ Serial Version UID ကို မရေးထားဖူးဆိုရင် Serialize လုပ်တဲ့အခါမှာ JVM ကနေ နှစ်သက်ရာ ID တစ်ခုကို Generate လုပ်ပေးမှာ ဖြစ်ပါတယ်။

ဒါပေမဲ့ Serial Version UID Calculation ဟာ Compiler Implementation အပေါ်မူတည်ပြီး ပြောင်းလဲတတ်တဲ့အတွက် Serial Version UID ကို Class အတွင်းမှာ မဖြစ်မနေရေးသားသင့်ပါတယ်။


Writing Objects (Serialization)

Java Program ထဲကနေ Memory အပေါ်မှာရှိတဲ့ Serializable Object တွေနဲ့ Serializable Object ရဲ့ Collection တွေကို Serialize လုပ်လိုတဲ့အခါမှာ ObjectOutputStream ကို အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။ ObjectOutputStream ကို အသုံးပြုပြီး Primitive Data တွေနဲ့ Serializable Object Graphs တွေကို Serialize လုပ်ပေးနိုင်မှာ ဖြစ်ပါတယ်။

Object တွေကို Serialize လုပ်တဲ့နေရာမှာလဲ File တွေမှာလဲ Serialize လုပ်နိုင်သလို Network ကို အသုံးပြုတဲ့ Socket Stream တွေနဲ့လဲ တွဲဖက် အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။ ObjectOutputStream ရဲ့ Constructor တွေကတော့ အောက်ပါအတိုင်း ဖြစ်ကြပါတယ်။

Constructor Description
ObjectOutputStream() ObjectOutputStream ရဲ့ Sub Class တွေအတွက် ပြင်ဆင်ထားပေးတဲ့ Constructor ဖြစ်ပါတယ်။
ObjectOutputStream(OutputStream out) OutputStream Object တစ်ခုကို အသုံးပြုပြီး ObjectOuputStream ကို တည်ဆောက်ရန် ပြင်ဆင်ထားတဲ့ Constructor ဖြစ်ပါတယ်။

package com.jdc.io.stream.ep5;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;

public class ObjectWriteTest {

    public static void main(String[] args) {
        Employee e = new Employee();
        e.setId(1);
        e.setName("Aung Aung");
        e.setPhone("09788986677");
        
        try(ObjectOutputStream out = new ObjectOutputStream(
                new FileOutputStream("employee.obj"))) {
            out.writeObject(e);
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }
}
အထက်ပါနမူနာအတိုင်း JVM Memory အပေါ်မှာရှိတဲ့ Object တွေကို Serialize လုပ်လိုပါက writeObject(Object obj) method ကို အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။


Reading Objects (Deserialization)

ObjectOutputStream ကို အသုံးပြုပြီး Serialize လုပ်ထားတဲ့ Primitive Data တွေနဲ့ Object တွေကို Deserialize လုပ်လိုတဲ့အခါ ObjectInputStream ကို အသုံးပြုရမှာ ဖြစ်ပါတယ်။

File ထဲမှာရှိတဲ့ Data တွေကို Deserialize လုပ်တဲ့အခါမျိုးမှာ ObjectInputStream ဟာ FileInputStream ကို အသုံးပြုပါတယ်။ ဒါကြောင့် File ထဲက Data တွေကို Read လုပ်လိုတဲ့အခါမျိုးမှာ InputStream Parameter နေရာမှာ FileInputStream Object ကို အသုံးပြုရမှာ ဖြစ်ပါတယ်။

တဖန် Remote System တစ်ခုကနေ Data တွေကို ရယူတဲ့အခါမျိုးမှာတော့ Socket Streams ကို အသုံးပြုပြီး Data တွေကို Deserialize လုပ်နိုင်ပါတယ်။

Constructor Description
ObjectInputStream() ObjectInputStream ရဲ့ Sub Class တွေအတွက် ပြင်ဆင်ထားပေးတဲ့ Constructor ဖြစ်ပါတယ်။
ObjectInputStream(InputStream in) OutputStream Object တစ်ခုကို အသုံးပြုပြီး ObjectOuputStream ကို တည်ဆောက်ရန် ပြင်ဆင်ထားတဲ့ Constructor ဖြစ်ပါတယ်။

package com.jdc.io.stream.ep5;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;

public class ObjectReadTest {

    public static void main(String[] args) {
        
        try(ObjectInputStream in = new ObjectInputStream(
                new FileInputStream("employee.obj"))) {
            
            Employee e = (Employee) in.readObject();
            
            System.out.println(e.getName());
            
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

ယခင် နမူနာဖြင့် Serialize လုပ်ထားတဲ့ Employee Object ကို Deserialize လုပ်လိုတဲ့အခါ အထက်ပါအတိုင်း ObjectInputStream ကို အသုံးပြုပြီး ရေးသားနိုင်ပါတယ်။ အထက်ပါအတိုင်း in.readObject() method ရဲ့ Return Type ဟာ Object ဖြစ်နေတဲ့အတွက် Employee အဖြစ်ပြန်ပြီး Cast လုပ်ပေးဖို့လိုအပ်ပါတယ်။

ဆက်ပါဦးမယ်
မင်းလွင်

January 11, 2017

A Glance to Java 9

Java SE 9 အကြောင်း အတော်လေးပြောလာကြပြီ။ ဘာပဲပြောပြော ၂၀၁၇ နှစ်ထဲမှာပဲ Release လုပ်ဖြစ်မှာတော့ သေချာတယ်။ Java SE 9 ရဲ့ အဓိက Feature လို့ပြောရရင်တော့ Project Jigsaw လို့ပဲ ပြောရမှာ ဖြစ်ပေမဲ့ ပြောင်းလဲမှု့တွေကတော့ အတော်လေးကိုများပါတယ်။

စမ်းသပ်မယ်ဆိုရင်တော့ JDC 9 Early Release ကို Download လုပ်လို့ရနေပါပြီ။

JDK 9 Download
https://jdk9.java.net/download/

အဓိကအားဖြင့် Language, Tools နဲ့ Library Features တွေမှာ ပြောင်းလဲမှုတွေကို တွေ့ရမှာ ဖြစ်ပါတယ်။ JDK 9 ရဲ့ Early Release လဲ Download လုပ်လို့ရပြီဖြစ်တဲ့အတွက် ဒီတစ်ခေါက်တော့ Java SE 9 မှာ ဘာတွေပြောင်းသွားမလဲဆိုတာကို လေ့လာရင်းမိတ်ဆက်သွားပါမယ်။

JEP ဆိုတာက Java Enhancement Proposal ရဲ့ အတိုကောက် အခေါ်အဝါ်ဖြစ်ပါတယ်။ Java နဲ့ ပတ်သက်တဲ့ ပြုပြင်ပြောင်းလဲမှူ့ဆိုင်ရာ အကြံပြုလွှာတွေဖြစ်ပါတယ်။ Java SE 9 မှာ ပါဝင်တဲ့ JEP တွေကတော့ အားလုံးပေါင်း ၈၈ခုရှိပါတယ်။

102: Process API Updates
110: HTTP 2 Client
143: Improve Contended Locking
158: Unified JVM Logging
165: Compiler Control
193: Variable Handles
197: Segmented Code Cache
199: Smart Java Compilation, Phase Two
200: The Modular JDK
201: Modular Source Code
211: Elide Deprecation Warnings on Import Statements
212: Resolve Lint and Doclint Warnings
213: Milling Project Coin
214: Remove GC Combinations Deprecated in JDK 8
215: Tiered Attribution for javac
216: Process Import Statements Correctly
217: Annotations Pipeline 2.0
219: Datagram Transport Layer Security (DTLS)
220: Modular Run-Time Images
221: Simplified Doclet API
222: jshell: The Java Shell (Read-Eval-Print Loop)
223: New Version-String Scheme
224: HTML5 Javadoc
225: Javadoc Search
226: UTF-8 Property Files
227: Unicode 7.0
228: Add More Diagnostic Commands
229: Create PKCS12 Keystores by Default
231: Remove Launch-Time JRE Version Selection
232: Improve Secure Application Performance
233: Generate Run-Time Compiler Tests Automatically
235: Test Class-File Attributes Generated by javac
236: Parser API for Nashorn
237: Linux/AArch64 Port
238: Multi-Release JAR Files
240: Remove the JVM TI hprof Agent
241: Remove the jhat Tool
243: Java-Level JVM Compiler Interface
244: TLS Application-Layer Protocol Negotiation Extension
245: Validate JVM Command-Line Flag Arguments
246: Leverage CPU Instructions for GHASH and RSA
247: Compile for Older Platform Versions
248: Make G1 the Default Garbage Collector
249: OCSP Stapling for TLS
250: Store Interned Strings in CDS Archives
251: Multi-Resolution Images
252: Use CLDR Locale Data by Default
253: Prepare JavaFX UI Controls & CSS APIs for Modularization
254: Compact Strings
255: Merge Selected Xerces 2.11.0 Updates into JAXP
256: BeanInfo Annotations
257: Update JavaFX/Media to Newer Version of GStreamer
258: HarfBuzz Font-Layout Engine
259: Stack-Walking API
260: Encapsulate Most Internal APIs
261: Module System
262: TIFF Image I/O
263: HiDPI Graphics on Windows and Linux
264: Platform Logging API and Service
265: Marlin Graphics Renderer
266: More Concurrency Updates
267: Unicode 8.0
268: XML Catalogs
269: Convenience Factory Methods for Collections
270: Reserved Stack Areas for Critical Sections
271: Unified GC Logging
272: Platform-Specific Desktop Features
273: DRBG-Based SecureRandom Implementations
274: Enhanced Method Handles
275: Modular Java Application Packaging
276: Dynamic Linking of Language-Defined Object Models
277: Enhanced Deprecation
278: Additional Tests for Humongous Objects in G1
279: Improve Test-Failure Troubleshooting
280: Indify String Concatenation
281: HotSpot C++ Unit-Test Framework
282: jlink: The Java Linker
283: Enable GTK 3 on Linux
284: New HotSpot Build System
285: Spin-Wait Hints
287: SHA-3 Hash Algorithms
288: Disable SHA-1 Certificates
289: Deprecate the Applet API
290: Filter Incoming Serialization Data
292: Implement Selected ECMAScript 6 Features in Nashorn
294: Linux/s390x Port
295: Ahead-of-Time Compilation
297: Unified arm32/arm64 Port

ခေါင်းစဉ်တွေကြီး ဖတ်ကြည့်ရင်တောင် Language ပိုင်းဆိုင်ရာ ပြောင်းလဲမှူ့ထက် Platform ဘက်မှာ ပိုပြီး အားသာတာကို တွေ့ရပါမယ်။ Keywords ကတော့ Modularity ပါပဲ။ jshell ကတော့ Java ကို သင်ကြားရာမှာ Statement တွေကို အလွယ်တကူသင်ကြားနိုင်မှာ ဖြစ်ပါတယ်။

နောက်တစ်ခုစိတ်ဝင်စားမိတာက HTTP2 Client ဟာလဲ​စိတ်ဝင်စားစရာ ဖြစ်ပါတယ်။ Tools နဲ့ JVM အစရှိတဲ့ Platform ပိုင်းဆိုင်ရာ ပြောင်းလဲမှု့တွေကများတာကို တွေ့ရပါတယ်။

ဆက်ပြီးလေ့လာသွားပါဦးမယ်။
လေးစားစွာဖြင့်
မင်းလွင်

January 5, 2017

Static Vs Instance

Q - Static နဲ့ Instance ကို အလွယ် ဘယ်လိုခွဲမလဲ


A - Java ကို လေ့လာကာစလူတွေ အမြဲတမ်းလိုလို ကြုံတွေ့တတ်တဲ့ မေးခွန်းတစ်ခုဖြစ်ပါတယ်။ ဒီမေးခွန်းကို ခွဲစိတ်ကြည့်မယ်ဆိုရင် အောက်ပါ မေးခွန်းလေးတွေ ထပ်ပြီးထွက်လာနိုင်ပါတယ်။

  1. Static ဆိုတဲ အဓိပ္ပါယ်နဲ့ Instance ဆိုတဲ့အဓိပ္ပါယ်
  2. ဘယ်လိုနေရာတွေမှာ Static နဲ့ Instance တို့ကိုခွဲပြီးရေးနိုင်လဲ
  3. ဘယ်လိုရေးရင် Static ဖြစ်ပြီး ဘယ်လိုရေးရင် Instance ဖြစ်သွားမလဲ
  4. Static နဲ့ Instance တွေကို ဘယ်လို Access လုပ်ကြမလဲ
  5. Static နဲ Instance တွေရဲ့ ထူးခြားချက်တွေကဘာတွေလဲ
  6. ဘယ်လိုနေရာမျိုးတွေမှာ Static ကို သုံးပြီး ဘယ်လိုနေရာမျိုးတွေမှာ Instance တွေကို သုံးရမလဲ 

Static ဆိုတဲ့အဓိပ္ပါယ် နဲ့ Instance ဆိုတဲ့အဓိပ္ပါယ်

တိုက်ရိုက်ပြန်ရင်တော့ Static ကို Dynamic မဟုတ်တဲ့အတွက် ကိန်းသေတွေလို့ပြောနိုင်မယ်။ ဒါပေမဲ့ ဒီနေရာမှာ ကတော့ Class နဲ့ ပတ်သက်တဲ့အရာတွေလို့ဆိုလိုနိုင်ပါတယ်။

ဒါဆိုရင် Class ကို ဘာလို့ရေးရတာလဲ။
  1. Object ဆောက်ဖို့၊ Object ရဲ့ State နဲ့ Behavior ကို သတ်မှတ်ပေးဖို့
  2. Utility အနေနဲ့ Function တွေကို ရေးသား အသုံးဖို့
Static ဆိုတာက Object အတွက်မဟုတ်ပဲ ဒုတိယ ရည်ရွယ်ချက်တွေကို ရေးသားတဲ့အခါမှာ Class ထဲမှာ ထားပြီး သုံးနိုင်တဲ့ Member တွေကို ဖေါ်ပြတဲ့နေရာမှာ အသုံးပြုပါတယ်။

Object တွေကို Instance တွေလို့လဲခေါ်လေ့ရှိပါတယ်။ ဒါ့ကြောင့် Instance ဆိုတာက Object နဲ့ဆိုင်တဲ့အရာတွေကို ဖေါ်ပြတဲ့အခါတွေမှာ သုံးပါတယ်။

ဒါ့ကြောင့် Instance Variable ဆိုရင် Object တွေနဲ့ ဆိုင်တဲ့ Variable တွေ ဖြစ်ပြီး Instance Method ဆိုရင် Object တွေမှာ သုံးလို့ရတဲ့ Method တွေလို့ မှတ်နိုင်ပါတယ်။

တနည်း Static Variable ဆိုရင် Class နဲ့ ဆိုင်တဲ့ Variable ဖြစ်ပြီး Object ဆောက်တဲ့အခါမှာ အဲ့ဒီအချက်အလက်တွေကို Object တစ်ခု ရဲ့ State အနေနဲ့ အသုံးပြုမှာ မဟုတ်ပါဘူး။ ပြီးတော့ Static Method တွေကလဲ Class ရဲ့ Utility Method တွေဖြစ်ကြပါတယ်။ ဒါ့ကြောင့် Class ကနေ အသုံးပြုရမှာ ဖြစ်ပါတယ်။

ဒီလိုမှတ်ရင်လဲရနိုင်တယ်။ Instance Member တွေရဲ့ Owner ဟာ Object ဖြစ်ပြီး Static Member တွေရဲ့ Owner ဟာ Class ဖြစ်ပါမယ်။


ဘယ်လိုနေရာတွေမှာ Static နဲ့ Instance တို့ကိုခွဲပြီးရေးနိုင်လဲ

Class ရဲ့ Member တွေမှာ Static နဲ့ Instance တို့ကို ခွဲပြီးရေးနိုင်တယ်။

ဒါဆို Class ရဲ့ Member တွေက ဘာတွေလဲ ဆိုတဲ့ မေးခွန်းက ပေါ်လာပြန်မယ်။ Class Body ထဲမှာ ရေးလို့ရတဲ့ အရာတွေဟာ အဲ့ဒီ Class ရဲ့ Member တွေ ဖြစ်ကြတယ်။ အဲ့ဒီနေရာမှာ Class ထဲမှာ ဘာတွေရေးလို့ရလဲ ဆိုတာကို မသိရင် Class Member တွေ ဘာတွေရှိတယ်ဆိုတာကို သိမှာ မဟုတ်ပြန်ဘူး။

Class ထဲမှာ ရေးလို့ရတာကတော့ အောက်ပါ အရာတွေဖြစ်ပါတယ်။
Members Static Instance Description
Variable Yes Yes
Methods Yes Yes
Constructors No Yes Object ဆောက်တဲ့အခါမှာသာ သုံးတဲ့အတွက် Static Constructor ဆိုတာမရှိပါဘူး
Nested Class Yes Yes
Nested Interface Yes Yes
Nested Enum Yes No Enum တွေဟာ Default Static Entity တွေ ဖြစ်တဲ့အတွက် Instance Enum ဆိုတာ မရှိပါဘူး။ အဲ့ဒီအတွက် Static Keyword ကို မရေးလဲ Static တွေ သာဖြစ်ကြပါတယ်

Nested Class, Interface နဲ့ Enum တွေကိုတော့ နောက်အခန်းတွေကျမှ ဆက်ပြီး ဖေါ်ပြသွားပါမယ်။ အခုတော့ ဘာတွေလဲလို့ မမေးပါနဲ့ ဦး။


ဘယ်လိုရေးရင် Static ဖြစ်ပြီး ဘယ်လိုရေးရင် Instance ဖြစ်သွားမလဲ

အလွယ်ပြောရမယ်ဆိုရင် Static ကော Instance ကော သတ်မှတ်နိုင်တဲ့ Member တွေမှာ static လို့ရေးထားရင် Static Member တွေဖြစ်ပြီး ဘာမှ မရေးထားရင် Instance Member တွေ ဖြစ်ကြတယ်။

တကယ်တော့ Class ကို ရေးရတဲ့ အဓိက ရည်ရွယ်ချက်ဟာ Object မှာပါတဲ့ State နဲ့ Behavior ကို Define လုပ်ပေးဖို့ဖြစ်တယ်။ အဲ့ဒီအတွက် Default အတိုင်းဆိုလို့ကတော့ Object အတွက်ကြီးပဲ ဖြစ်တယ်။ Object ရဲ့ State တွေအတွက် Variable တွေနဲ့ သတ်မှတ်ပေးတယ်။ အဲ့ဒီတော့ Default အတိုင်း ဆိုလို့ကတော့ Variable တွေဟာ Object ရဲ့ State အတွက် ဖြစ်တဲ့အတွက် Instance Variable တွေဖြစ်မှာပဲ။

Method တွေကလဲ Object တွေရဲ့ Behavior ကို သတ်မှတ်ဖို့ရေးတယ်။ အဲ့ဒီအတွက် Default အတိုင်းဆိုလို့ကတော့ Instance Method တွေ ဖြစ်နေမှာပါပဲ။

အဲ့ဒီ Default တန်ဖိုးတွေကို ပြင်ချင်တော့မှ၊ ဆိုလိုတာက Variable တွေ Method တွေဟာ Object အတွက်မဟုတ်ဘူး၊ Class ထဲမှာပဲ သုံးမှာပါလို့ ဖေါ်ပြနိုင်အောင် Static Modifier ကို သုံးပြီး ရေးသားရမှာ ဖြစ်ပါတယ်။
public class Person {

    // static variable
    static int count;

    // instance variable
    String name;

    // instance method
    public void showName() {
        System.out.println(name);
    }

    // static method
    public static void showStudentCount() {
        System.out.println(count);
    }
}
ဒါ့ကြောင့် Variable တွေ Method တွေရှေ့မှာ ဘာမှမပါရင် Instance တွေ ဖြစ်ကြပြီး static ပါရင် Static တွေဖြစ်တယ်လို့ ခွဲပြီး မှတ်နိုင်မှာ ဖြစ်ပါတယ်။


Static နဲ့ Instance တွေကို ဘယ်လို Access လုပ်ကြမလဲ

ဒီနေရာမှာ အရေးကြီးတာက Owner ဟာ ဘယ်ဟာလဲဆိုတာကို သိဖို့လိုအပ်ပါတယ်။ Static Members တွေရဲ့ Owner ဟာ Class ဖြစ်ပြီး Instance Member တွေရဲ့ Owner ဟာ Object ဖြစ်ပါတယ်။ Members တွေကို Access လုပ်တဲ့ အခါမှာ Class တစ်ခုထဲကနေ Access လုပ်တာနဲ့ အဲ့ဒီ Class ရဲ့ အပြင်ကနေ Access လုပ်တာဆိုပြီး ၂ မျိုးရှိနိုင်ပါလိမ့်မယ်။

Class တစ်ခုထဲကနေ Access လုပ်မယ်ဆိုရင်တော့ Owner ကို မရေးပဲနေလို့ရပါတယ်။ ဒါ့ကြောင့် Variable ပဲ ဖြစ်ဖြစ် Method ပဲဖြစ်ဖြစ် အဲ့ဒီအတိုင်းကို Access လုပ်နိုင်လိမ့်မယ်။ (ဒီနေရာမှာ Variable Hiding တို့ Super Class ထဲက Member တွေကိုသုံးချင်ရင်ကောတို့၊ ခေါ်လို့ရတာမရတာတို့ ရှိပါသေးတယ်။ ဒါတွေကိုတော့ နောက်အခန်းတွေကြမှ ဆက်ပြောကြရအောင်။)

အဲ့ဒီ Class ရဲ့ အပြင်ကနေ Access လုပ်မယ်ဆိုရင်တော့ Owner ကနေ တဆင့် Access လုပ်ရမှာ ဖြစ်ပါတယ်။ [Owner].[Member] ဆိုပြီး Access လုပ်ရမှာ ဖြစ်တယ်။ Variable တွေဆိုရင်တော့ owner.variable ဆိုပြီး ရေးရပါမယ်။ Method တွေဆိုရင်တော့ owner.method() ဆိုပြီးရေးရမှာပါ။ Method တွေကို Access လုပ်တဲ့အခါမှာတော့ Method Signature အတိုင်း Parameter တွေကို ရေးသားပေးရမှာ ဖြစ်ပါတယ်။
public class PersonTest {

    public static void main(String [] args) {

        // static variable
        Person.count = 10;

        // static method
        Person.showStudentCount();
    }
}

Person Class ထဲမှာ ပါတဲ့ count ဟာ Static Variable ဖြစ်တဲ့အတွက် Owner ဟာ Class ဖြစ်တဲ့အတွက် Class ကနေတဆင့် Access လုပ်ရမှာပါ။ ဒါ့ကြောင့် Person.count ဆိုပြီး ရေးရမှာ ဖြစ်ပါတယ်။ တဖန် showStudentCount() ဆိုတဲ့ Method ဟာလဲ Static Method ဖြစ်တဲ့အတွက် Person.showStudentCount() ဆိုပြီး Person Class ကနေတဆင့် ရေးသားရမှာ ဖြစ်ပါတယ်။
public class PersonTest {

    public static void main(String [] args) {

     Person p = new Person();

        // static variable
        p.name = "Thidar";

        // static method
        p.showName();
    }
}

Instance Member တွေကို Access လုပ်ချင်ပြီ ဆိုရင်တော့ Owner ဟာ Object ဖြစ်တဲ့အတွက် Object တွေကနေမှ ဆက်သွယ်လို့ရမှာပါ။ ဒါ့ကြောင် Person အမျိုးအစား ဖြစ်တဲ့ p variable နေရာမှာ new Person() ဆိုပြီး Object ဆောက်ပြီး သူ့ကို Reference အနေနဲ့ ပေးနေပါတယ်။

ပြီးတော့မှ instance variable ဖြစ်တဲ့ name ကို p.name ဆိုပြီး Access လုပ်ရမှာ ဖြစ်ပါတယ်။ အလားတူပဲ instance method ဖြစ်တဲ့ showName ကို Access လုပ်တဲ့အခါမှာလဲ onwer object ဖြစ်တဲ့ p ကနေတဆင့် p.showName() ဆိုပြီး Access လုပ်နေတာဖြစ်ပါတယ်။


Static နဲ Instance တွေရဲ့ ထူးခြားချက်တွေကဘာတွေလဲ

Static နဲ့ Instance တို့ရဲ့ ထူးခြားချက်တွေလို့ပြောလာရင် Class နဲ့ Object တို့ရဲ့ ထူးခြားချက်တွေလို ပြောလာတာနဲ့ အတူတူဖြစ်ပါလိမ့်မယ်။

အရင်ဆုံး Class ရဲ့ ထူးခြားချက်ဆိုတာကို ကြည့်အောင်။ Class တွေဟာ JVM တစ်ခုလုံးမှာ တစ်ခုထဲသာရှိပါမယ်။ Runtime ကနေ အလုပ်လုပ်နေရင်းနဲ့ Class တစ်ခုကို Declare လုပ်နေတာကို တွေ့ရင် JVM ရဲ့ Memory ပေါ်မှာ ရှိလားဆိုတာကို ကြည့်မယ်။ မရှိဘူးဆိုရင် Class Path ထဲကနေ အဲ့ဒီ Class ကို Memory ပေါ်ကို Load လုပ်ပါမယ်။ တကယ်လို့ ရှိပြီးသားဆိုရင်တော့ အဲ့ဒီ Class ကိုပဲ အသုံးပြုပါလိမ့်မယ်။ ဒါ့ကြောင့် Class တွေဟာ JVM ရဲ့ Memory ပေါ်မှာ တစ်ခုထဲသာ ရှိနေမှာ ဖြစ်ပါတယ်။

Object တွေကကော။ သူတို့တွေကတော့ new keyword နဲ Constructor ကို ခေါ်လိုက်တိုင်း Object အသစ်တစ်ခုကို တည်ဆောက်ပါတယ်။ အဲ့ဒီ Object တွေက တစ်ခုနဲ့ တစ်ခု ပတ်သက်မှူ့မရှိပါဘူး။ ကျွန်တော်တို့ Class တစ်ခုကနေ Object objectA နဲ့ objectB ကို တည်ဆောက်ခဲ့တယ်ဆိုပါစို့။ objectA မှာပါတဲ့ State တွေဟာ objectA နဲ့သာ ဆိုင်ပြီး objectB နဲ့ ပတ်သက်မှာ မဟုတ်ပါဘူး။

ဆက်ပြီး Object ကို Instantiate လုပ်တယ်ဆိုတာ JVM ပေါ်မှာ လက်တွေ့ ဘယ်လို ဖြစ်သွားလဲ ဆိုတဲ့ ဘက်ကနေ ကြည့်ကြရအောင်။ new keyword ကို သုံးပြီး Object ဆောက်ရင် JVM ပေါ်မှာ Class ကနေ Object နဲ့ ဆိုင်တဲ့ Instance Variable တွေကို Copy ကူးသွားပြီး Heap Memory ပေါ်မှာ Object ကို သွားဆောက်ပါတယ်။ Copy ကူးသွားတဲ့နေရာမှာ Static Variable တွေမပါပါဘူး။ Class နဲ့သာ ပတ်သက်တဲ့အရာတွေ ဖြစ်တဲ့ အတွက် Class ထဲမှာပဲ ချန်ထားခဲ့ပါတယ်။


ထူးခြားချက် တွေကို Variable တွေ ဘက်ကကြည့်ကြရအောင်။

Static Variable တွေဟာ Class ထဲမှာပဲ ရှိနေမှာဖြစ်ပြီး၊ Class ဟာလဲ JVM တစ်ခုလုံးမှာ တစ်ခုထဲသာရှိနေမှာ ဖြစ်တဲ့အတွက် သူတို့တွေဟာလဲ JVM ထဲမှာ တစ်ခုထဲသာ ရှိနေမှာပဲဖြစ်တယ်။ ဘယ်နေရာကပဲ Static Variable ကို Access လုပ်လုပ် တစ်ခုထဲသော အဲ့ဒီ Variable ရဲ့ တန်ဖိုးကိုပဲ ရရှိမှာ ဖြစ်ပါတယ်။

Instance Variable တွေကတော့ Object ဆောက်လိုက်တိုင်း Class ကနေ Copy ကူးသွားတာဖြစ်တဲ့အတွက် အဲ့ဒီ Object တစ်ခုချင်းစီနဲ့သာ ပတ်သက်ပါတယ်။ ဒါ့ကြောင့် Object တစ်ခုရဲ့ Instance Variable ကို တန်ဖိုးပြောင်းရင် အဲ့ဒီ Object ကပိုင်တဲ့ Instance Variable ရဲ့တန်ဖိုးသာ ပြောင်းသွားမှာ ဖြစ်တယ်။ တစ်ခြား Object တွေရဲ့ တန်ဖိုးဟာ ပြောင်းသွားမှာ မဟုတ်ပါဘူး။


Method တွေရဲ့ ထူးခြားချက်တွေကကောဘယ်လိုလဲ။

Static Method တွေဟာ Class တွေနဲ့သာဆိုင်တယ်။ အဲ့ဒါကြောင့် Static Method တွေကို Class တွေကနေတဆင့် Invoke လုပ်ကြမှာ ဖြစ်တယ်။ ဒီလို Static Method တွေကို Invoke လုပ်တဲ့ အချိန်မှာ Object တွေကို မဆောက်ရသေးတာလဲ ဖြစ်နိုင်တယ်။ ဆောက်ပြီးပြန်ရင်လဲ new ခေါ်တိုင်း Object ဆိုတာ ဆောက်လို့ရနေတဲ့ အတွက် Static Method ထဲကနေ Instance Variable ကို Access လုပ်ပါ၊ ဒါမှမဟုတ် Instance Method ကို Invoke လုပ်ပါလို့ ခိုင်းလာရင် ဘယ် Object ရဲ့ variable ကို ဘယ် Object ရဲ့ Method ကို Access လုပ်ရမှန်း သိနိုင်မှာ မဟုတ်ဘူး။

ဒါ့ကြောင့် Static Method တွေဟာ Static Variable တွေကိုသာ Access လုပ်နိုင်ပြီး Static Method တွေ အချင်းချင်းသာ Invoke လုပ်နိုင်မှာ ဖြစ်ပါတယ်။  Static Method တစ်ခုကနေ တစ်ခြား Method တစ်ခုကို Invoke လုပ်တော့မယ်ဆိုရင် အဲ့ဒီ Method ဟာ Static Method ဖြစ်နေဖို့လိုအပ်ပါတယ်။ Static Method ကနေ Instance Method ကို Invoke လုပ်ချင်ရင်တော့ Object ဆောက်ပြီးမှသာ Invoke လုပ်နိုင်မှာ ဖြစ်ပါတယ်။

Instance Method တွေကတော့ Object တွေကပိုင်တဲ့အတွက် Owner ဖြစ်တဲ့ Object တစ်ခုချင်းစီနဲ့ ပဲဆိုင်ပါတယ်။ ပြီးတော့ Instance Method တွေကနေ Instance Variable တွေကိုလဲ Access လုပ်နိုင်သလို Instance Method တွေကိုလဲ Invoke လုပ်နိုင်ပါတယ်။ သတိထားဖို့လိုတာက Owner Object ကနေ Instance ကို Invoke လုပ်လိုက်ရင် အဲ့ဒီ method ထဲကနေ Access လုပ်နေတဲ့ Instance Variable တွေရှိရင်လဲ အဲ့ဒီ Object ရဲ့ Variable ကိုပဲ Access လုပ်မှာ ဖြစ်ပြီး၊ တစ်ခြား Instance Method တွေကို Invoke လုပ်နေရင်လဲ အဲ့ဒီ​ Object ရဲ့ method ကိုပဲ Invoke လုပ်နေတာပဲ ဖြစ်ပါတယ်။ တစ်ခြား Object တွေနဲ့ ပတ်သက်မှူ့လုံးဝမရှိပါ။

တဖန် Instance Method ကနေ Static Variable တွေကိုလဲ Access လုပ်နိုင်ပြီး Static Method တွေကိုလဲ Invoke လုပ်နိုင်ပါတယ်။ ဘာလို့လဲ ဆိုတော့ Static Member တွေက Object မဆောက်ခင်ကထဲက Memory ပေါ်မှာ ရှိပြီးသားဖြစ်နေပြီး တစ်ခုထဲသာ ရှိတာဖြစ်တဲ့အတွက် ဘယ် Member ကို Access လုပ်မယ်ဆိုတာကို သိနေနိုင်တဲ့အတွက်ဖြစ်ပါတယ်။


Static နဲ့ Instance ကိုဘယ်လိုခွဲ သုံးရမလဲ

Static Members တွေနဲ့ Instance Members တွေရဲ့ ထူးခြားချက်ကို ကြည့်ရင် သိနိုင်ပါတယ်။ Static တွေဟာ Instance တွေလို Instance တစ်ခုချင်းစီအတွက် State တွေကို ပိုင်လို့မရဘူး။ ပြီးတော့ သူတို့တွေဟာ JVM ပေါ်မှာ တစ်ခုထဲရှိတဲ့ အရာတွေ ဖြစ်ကြတယ်။

အဲ့ဒီတော့ Static Method တွေကို State ပိုင်စရာမလိုအပ်တဲ့ Utility Function တွေမှာ ရေးသား အသုံးပြုနိုင်ပါတယ်။ တဖန် Static Variable တွေကလဲ JVM တစ်ခုလုံးမှာ တစ်ခုထဲသာရှိတဲ့ Variable တွေ ဖြစ်လာမှာ ဖြစ်တဲ့အတွက် Application တစ်ခုလုံးမှာ ဘုံအနေနဲ့ အသုံးပြုလိုတဲ့ အချက်အလက်တွေ၊ Object တွေကို Static Variable တွေအနေနဲ့ အသုံးပြုနိုင်ပါတယ်။

Static Variable ရဲ့ ထူးခြားချက်ကို အသုံးပြုပြီး Singleton Patterns လိုမျိုးကိုလဲ ရေးသားနိုင်ပါတယ်။ Disktop Application မျိုးမှာ Session ကို အသုံးပြုလို့မရဘူး။ အဲ့ဒီအစား Static Variable တွေကို Chache အနေနဲ့ ထားပြီး Data တွေကို Share လုပ်ပြီး အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။

ဒါဖြင့် Instance Member တွေကကော။ ဒါကလွယ်ပါတယ်ဗျာ။ Object တစ်ခုချင်းစီမှာ ပိုင်ဆိုင်စေလိုတဲ့ State တွေ Behavior တွေဆိုရင် Instance Member တွေ သုံးပြီး ရေးလိုက်ရုံပေါ့ဗျာ။

မေးကြပါဗျာ။ ကြိုးစားပြီးဖြေသွားပါမယ်။
လေးစားစွာဖြင့်
မင်းလွင်

Backing Beans


JSF ဟာ Java EE 5 ကထဲက ပါဝင်ခဲ့တဲ့ Java EE ရဲ့ Standard API တစ်ခုဖြစ်ပါတယ်။ အဲ့ဒီတုန်းက JSF ရဲ့ Backing Beans တွေအနေနဲ့ အသုံးပြုနိုင်ခဲ့တာကတော့ Managed Beans တစ်မျိုးထဲရှိခဲ့ပါတယ်။ ဒါပေမဲ့ Java EE 6 အရောက်မှာ CDI ကို အသုံးပြုလာနိုင်ခဲ့ပြီး CDI ရဲ့ Named Beans တွေကို JSF ရဲ့ View တွေကနေ Access လုပ်လာနိုင်ခဲ့ပြီး JSF ရဲ့ Backing Beans တွေ အနေနဲ့ အသုံးပြုလာနိုင်ပါတယ်။

ဒါ့ကြောင့် JSF ရဲ့ Backing Bean အနေနဲ့အသုံးပြုနိုင်ဖို့အတွက် လက်ရှိအနေအထားအရ ၂ မျိုးရေးသားနိုင်ပါတယ်။ ဒါပေမဲ့ Java EE 7 အရောက်မှာ CDI Named Beans တွေကိုသာ အသုံးပြုသွားမယ်လို့ တရားဝင် ထုတ်ပြန်ပြောကြားထားတဲ့အတွက် CDI Named Beans တွေကို ဦးစားပေးဖေါ်ပြသွားပါမယ်။


Writing Managed Beans

မည်သည့် POJO Class ကို မဆို JSF ရဲ့ Managed Bean အနေနဲ့ အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။ Managed Bean အနေနဲ့ အသုံးပြုနိုင်ရန် အောက်ပါ အချက်အလက်များကို လိုက်နာဖို့လိုအပ်ပါတယ်။
  • javax.faces.bean.ManagedBean Annotation နဲ့ JSF Scope Annotation တစ်ခုခုကို တပ်ဆင်ရေးသားထားရပါမယ်
  • Java Beans Technology ကို လိုက်နာပြီး ရေးသားထားရပါမယ်
  • Final Class တစ်ခု မဟုတ်ရပါဘူး
  • Default Constructor တစ်ခု မဖြစ်မနေပါဝင်ရပါမယ်
@ManagedBean
@RequestScope
public class StudentBean {
    
    private String name;
    private int english;
    private int burmese;
    private int maths;
    private int chemistory;
    private int biology;
    private int physics;

    // getters & Setters of Properties

    public int getTotal() {
        return english + burmese + maths + chemistory + biology + physics;
    }

    public int getAverage() {
        return getTotal() / 6;
    }
}

အထက်ပါအတိုင်း ရေးသားထားရင်တော့ Backing Bean အနေနဲ့ အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။ တကယ်လို့ Properties တွေကို View ထဲမှာရှိတဲ့ Component Value တွေနဲ့ Bind လုပ်ချင်ရင်တော့ Java Beans Naming Rule ကိုလိုက်နာပြီးရေးသားထားတဲ့ getter / setter method တွေ ရေးသားထားဖို့လိုအပ်ပါတယ်။

getter / setter မပါပဲ View ထဲကနေ Reference လုပ်ထားမယ်ဆိုပါက PropertyNotFoundException ကို ဖြစ်ပေါ်စေမှာ ဖြစ်ပါတယ်။ ဒီထက်ပိုပြီး Properties ထဲမှာ မရှိပေမဲ့ getter method တစ်ခုကို ရေးသားထားမယ်ဆိုရင်လဲ View ထဲကနေ Reference လုပ်လို့ရမှာ ဖြစ်ပါတယ်။

အထက်ပါ​နမူနာအရ total နဲ့ average တို့ဟာ Beans ရဲ့ Property တွေ မဟုတ်ကြပါဘူး။ ဒါပေမဲ့ getTotal() နဲ့ getAverage() method တို့ကို ရေးသားထားတဲ့အတွက် EL Expression ထဲကနေ total တို့ average တို့အမည်နဲ့ Reference လုပ်လို့ရမှာ ဖြစ်ပါတယ်။


Writing Named Beans

CDI Beans တစ်ခုခုမှာ @Named Annotation ကို တပ်ဆင်ရေးသားလိုက်တာနဲ့ JSF ရဲ့ View ထဲကနေ ဆက်သွယ်ရေးသားနိုင်မှာ ဖြစ်ပါတယ်။ ဒါ့ကြောင့် Named Beans တွေကို အသုံးပြုတဲ့နေရာမှာ CDI Scoped Beans တွေကို အသုံးပြုတဲ့ပုံစံနဲ့ Produce လုပ်ထားတဲ့ Beans တွေကို အသုံးပြုတဲ့ပုံစံ ဆိုပြီး ၂မျိုးရှိနိုင်ပါတယ်။


CDI Scope Beans

CDI Scoped Beans တွေမှာ @Named Annotation ကို ရေးပြီး Backing Beans အနေနဲ့ အသုံးပြုနိုင်ပါတယ်။ တဖန် @Named နဲ့ @RequestScope တို့ကို ရေးသားရလွယ်ကူစေနရန် @Model ဆိုတဲ့ Annotation ကိုလဲ ပြင်ဆင်ထားပါတယ်။ ဒါ့ကြောင့် @Model လို့ရေးလိုက်တာနဲ့ @Named နဲ့ @RequestScope တို့ကိုတွဲရေးတာနဲ့ အတူတူပဲ ဖြစ်ပါလိမ့်မယ်။
@Model
public class StudentBean {
    
    private String name;
    private int english;
    private int burmese;
    private int maths;
    private int chemistory;
    private int biology;
    private int physics;

    // getters & Setters of Properties

    public int getTotal() {
        return english + burmese + maths + chemistory + biology + physics;
    }

    public int getAverage() {
        return getTotal() / 6;
    }
}

Properties တွေကို Access လုပ်တာကတော့ Managed Beans တွေနဲ့ အတူတူပဲ ဖြစ်ပါတယ်။


Produced CDI Beans

@Named Annotation ကို အသုံးပြုပြီး Produce လုပ်ထားတဲ့ Beans တွေကိုလဲ EL Expression ကို အသုံးပြုပြီး Access လုပ်လို့ရပါတယ်။
@ApplicationScope
public class CategoryProducer {
    
    @Named
    @Produces
    private List<Category> categories;

    @Inject
    private CategoryService service;

    @PostConstruct
    private void load() {
        categories = service.getAll();
    }

}

အထက်ပါ နမူနာထဲမှာ categories ကို Produce လုပ်ထားပြီး @Named ကို ရေးသားထားပါတယ်။ ထိုသို့ရေးသားထားပါက View ထဲကနေ EL Expression ကို အသုံးပြုပြီး Access လုပ်နိုင်မှာ ဖြစ်ပါတယ်။


Managed Beans Vs Named Beans

အထက်တွင် လေ့လာခဲ့သလိုပဲ JSF ရဲ့ Managed Beans တွေကော CDI ရဲ့ Named Beans တွေကိုပါ Backing Beans တွေ အနေနဲ့ အသုံးပြုနိုင်တာကို သိခဲ့ရပါပြီ။ ဒီတစ်ခေါက်တော့ Managed Beans တွေနဲ့ Named Beans တွေဟာ ဘယ်လိုကွာခြားလဲ ဆိုတာကို လေ့လာသွားပါမယ်။

ရေးလို့ရသော ပတ်ဝန်းကျင်ဘက်ကနေကြည့်မယ်ဆိုရင် CDI Named Beans တွေကို CDI ကို သုံးလို့ရတဲ့ Java EE Container တွေရှိမှသာ အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။ Tomcat လို Web Container သာပါတဲ့ Application Server တွေပေါ်မှာဆိုရင် Default အတိုင်းဆိုရင် CDI Named Beans တွေကို အသုံးပြုနိုင်မှာ မဟုတ်ပါဘူး။ Light Weight CDI Container တွေနဲ့ တွဲသုံးမယ်ဆိုရင်တော့ ဖြစ်နိုင်ပါတယ်။

JSF Managed Beans တွေကိုတော့ JSF Library ကို ထည့်သွင်းပြီး အသုံးပြုမယ်ဆိုရင် Tomcat လိုပတ်ဝန်းကျင်မှာလဲ အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်။ တဖန် CDI ကို သုံးလို့ရတာကလဲ JSF 2 ရောက်မှ ဖြစ်တဲ့အတွက် JSF 2 မတိုင်ခင်က Version တွေမှာ ဆိုရင် CDI Named Beans တွေကို ရေးသားလို့ရမှာ မဟုတ်ပါဘူး။

ဒါ့အပြင် @ManagedProperty ဆိုတဲ့ Annotation ဟာ JSF ရဲ့ Managed Bean တွေမှာသာ သုံးလို့ရတာ ဖြစ်ပြီး Named Bean တွေမှာ အသုံးပြုလို့မရပါဘူး။ Scope တွေနဲ့ပတ်သက်လာရင် CDI ရဲ့ Scope တွေဟာ JSF ရဲ့ Scope တွေထက်ပိုပြီး Flexable ဖြစ်ပါတယ်။ @FlowScope နဲ့ @ConversationScope တို့ကို CDI Named Beans တွေမှာသာ အသုံးပြုလို့ရမှာ ဖြစ်ပြီး Managed Beans တွေမှာ အသုံးပြုလို့ရမှာ မဟုတ်ပါဘူး။

မိမိရဲ့ ပတ်ဝန်းကျင် နဲ့ Application ရဲ့ Requirements အပေါ်မှာ မူတည်ပြီး ဘယ်လို Beans ကို သုံးမလဲ​ဆိုတာကို ရွေးချယ် အသုံးပြုသင့်ပါတယ်။


Backing Beans တွေထဲမှာ ဘာတွေရေးသင့်သလဲ

Backing Beans တွေလို့ပြောပေမဲ့ ဒီ Beans တွေအားလုံးဟာ POJO တွေ ဖြစ်ကြပါတယ်။ ဒါ့ကြောင့် ဘာတွေရေးလို့ရလဲဆိုရင် Java မှာ ရေးလို့ရတာတွေကို ရေးလို့ရမှာ ဖြစ်ပါတယ်။ ဥပမာအားဖြင့် DataSource တွေ EntityManager တို့ကို Inject လုပ်ပြီးရင် Database ကို Access လုပ်တာတွေလဲ ရေးလို့ရတယ်ဗျာ။ JMS တွေကို Inject လုပ်ပြီး ရေးမယ်ဆိုလဲ ဖြစ်တာပဲ။ ဒါပေမဲ့ ဒါတွေဟာ ဖြစ်သင့်သလားဆိုတာကို ပြန်ပြီး လေ့လာကြည့်ကြရအောင်။

Backing Beans တွေဟာ JSF ရဲ့ Model နေရာမှာ တာဝန်ယူထားပါတယ်။ အဲ့ဒီအတွက် Model ရဲ့ တာဝန်တွေကို Backing Beans တွေမှာ ရေးခိုင်းတာဟာ သဘာဝကျပါတယ်။ ဒါဖြင့် MVC ထဲမှာ Model ရဲ့ တာဝန်က ဘာလဲ။ Model တွဟာ View တွေ အတွက် Data တွေကို Support လုပ်ပေးနိုင်ရမယ်။ View ထဲကနေပေးလာတဲ့ Input တွေကို လက်ခံယူနိုင်ရမယ်။ ပြီးတော့ Business Logic တွေကို Encapsulate လုပ်ပေးနိုင်ရပါမယ်။ဒါဆိုရင် Backing Beans တွေထဲမှာ ဘာတွေ ရေးသင့်သလဲ ဆိုတာကို မြင်လာပါလိမ့်မယ်။ View အတွက် Data တွေကို Properties တွေအနေနဲ့ ရေးသားသင့်ပါတယ်။ ပြီးတော့ Business Logic တွေကို အကောင် အထည်ဖေါ်ဖို့အတွက် Delegate လုပ်မည့် Business Modules တွေဖြစ်တဲ့ EJB Beans တွေ CDI Beans တွေကို ရေးသား သင့်ပါတယ်။ ပြီးတော့ View ကနေ Business Logic တွေကို Invoke လုပ်နိုင်ဖို့အတွက် Action Method တွေ Action Listener Method တွေကို လိုအပ်သလို ရေးသားသင့်ပါတယ်။
@Model
public class CustomerRegistrationBean {

    private Customer customer;

    @Inject
    private CustomerService service;

    @PostConstruct
    private void init() {
        customer = new Customer();
    }

    public void getCustomer() {
        return customer;
    }

    public void setCustomer(Customer customer) {
        this.customer = customer;
    }

    public String saveCustomer() {
        service.save(customer);
        return "customer-list?faces-redirect=true";
    }

}

အထက်ပါ နမူနာမှာတော့ customer ဟာ View နဲ့ Bind လုပ်မည့် property ဖြစ်တဲ့ အတွက် မဖြစ်မနေ getter / setter ကို ရေးသားထားဖို့လိုအပ်ပါတယ်။ တဖန် service object ဟာ Business Logic တွေကို Delegate လုပ်မည့် Bean ဖြစ်တဲ့ အတွက် Inject လုပ်ထားရင်ရပါပြီ။ getter / setter မလိုအပ်ပါဘူး။

saveCustomer method ကတော့ Action Method ဖြစ်ပါတယ်။ Return Type ကို String ကို သတ်မှတ်ပေးရန်လိုအပ်ပြီး ဘယ် Page ကို Navigate လုပ်မလဲဆိုတဲ့ Logical View Name ကို Return ပြန်ပေးရမှာ ဖြစ်ပါတယ်။

ဒီတစ်ခေါက်တော့ Backing Beans ဆိုတာဘာလဲ ဘယ်လိုရေးသင့်သလဲ ဆိုတာကို ဖေါ်ပြခဲ့ပါတယ်။ နောက်တစ်ခေါက်မှ View ထဲကနေ Backing Beans ကို ဘယ်လို Access လုပ်မယ်ဆိုတာကို ဖေါ်ပြသွားပါမယ်။

ဆက်ပါဦးမယ်
မင်းလွင်

January 3, 2017

File

Java IO API ဟာ JDK version 1.0 ကထဲကပါဝင်လာခဲ့တဲ့ Input Output ကို လုပ်ဆောင်ဖို့အတွက် API တစ်ခုဖြစ်ပါတယ်။ File System ထဲမှာ ရှိတဲ့ File တွေ Directory တွေရဲ့ Path ကို ကိုယ်စားပြုဖို့အတွက် java.io.File Class ကို ပြင်ဆင်ထားပါတယ်။ File Class ဟာ Serializable နဲ့ Comparable<File> ကို Implement လုပ်ထားတဲ့ Class တစ်ခုဖြစ်ပါတယ်။


How To Create File Object


အရင်ဦးဆုံး File Object တစ်ခုကို ဘယ်လို တည်ဆောက်မလဲ ဆိုတာကနေစပြီး လေ့လာကြည့်ကြရအောင်။ File Object ကို တည်ဆောက်ဖို့ အတွက် Constructors တွေကို ပြင်ဆင်ထားပါတယ်။ File Object ကို တည်ဆောက်တဲ့ နေရာမှာ လက်ရှိရှိပြီးသား File Directory တွေကိုကိုယ်စားပြုတဲ့ Object တွေကိုလဲ တည်ဆောက်နိုင်သလို၊ လက်တွေ့မှာ မရှိသော်လည်း Virtually တည်ဆောက်ထားလို့ရပါတယ်။ File Object ကို တည်ဆောက်ပြီး လိုအပ်လာတဲ့အခါကျမှ Create လုပ်လို့လဲ ရနိုင်ပါတယ်။ ဒါဆို File Class ထဲမှာပါတဲ့ Constructors တွေကို လေ့လာကြည့်ကြရအောင်။

Constructor Description
File(File parent, String child) Parent ဖြစ်တဲ့ File Object တစ်ခုနဲ့ Child Path Name တို့ဖြင့် File Object ကို တည်ဆောက်နိုင်တဲ့ Constructor ဖြစ်ပါတယ်
File(String pathname) File Directory ရဲ့ Path String ကနေ File Object ကို တည်ဆောက်နိုင်တဲ့ Constructor ဖြစ်ပါတယ်။ Path အနေနဲ့ Absolute Path ကော Relative Path ကို ပါ အသုံးပြုနိုင်မှာ ဖြစ်ပါတယ်
File(String parent, String child) File Directory တို့ရှိနေတဲ့ Directory Path နဲ့ File Name တို့ကနေ File Object ကို တည်ဆောက်နိုင်တဲ့ Constructor ဖြစ်ပါတယ်။
File(URI uri) File Directory တို့ကိုဖေါ်ပြနိုင်တဲ့ URI Object ကနေတဆင့် File Object ကိုတည်ဆောက်နိုင်တဲ့ Costructor ဖြစ်ပါတယ်။

File Class ရဲ့ Constructor တွေကို လေ့လာကြည့်ရင် File တစ်ခုကို တည်ဆောက်ဖို့အတွက်က အဲ့ဒီ File ရဲ့ Path ကို ဖေါ်ပြပေးနိုင်ဖို့လိုတာကို တွေ့ရပါမယ်။ အဲ့ဒီ Path ကို ဖေါ်ပြတဲ့နေရာမှာ Absoulte Path နဲ့လည်း ဖေါ်ပြနိုင်သလို Relative Path နဲ့ လည်းဖေါ်ပြနိုင်မှာ ဖြစ်ပါတယ်။
import java.io.*;

public class FileCreation {
    
    public static void main(String [] args) {

        // File Path
        File file1 = new File("file1");

        // Parent File and File Path
        File file2 = new File(file1, "file2.txt");

        // Parent File Path and File Path
        File file3 = new File("file1", "file3.txt");

        // URI
        URI uri = new URI("c:\\file1\\file4.txt");
        File file4 = new File(uri);
    }
}


Create & Delete File

File Object ကနေ File Directory တွေကို တည်ဆောက်နိုင်ဖို့၊ ပြီးတော့ ရှိပြီးသား File တွေကို ဖျက်နိုင်ဖို့အတွက် အောက်ပါ Methods တွေကို အသုံးပြုနိုင်ပါတယ်။

Method Return Type & Description
createNewFile() boolean

File Object မှာ သတ်မှတ်ထားခဲ့တဲ့ Abstract Path Name ဖြင့် Empty New File တစ်ခုကို တည်ဆောက်ပေးပါလိမ့်မယ်။ တကယ်လို့ Path အတိုင်း File ဟာရှိနေမယ်ဆိုရင် ဆောက်ပေးနိုင်မှာ မဟုတ်ပါဘူး။ File ကို တည်ဆောက်နိုင်ခဲ့ရင် true ကို Return လုပ်မှာ ဖြစ်ပြီး မဆောက်နိုင်ခဲ့ပါက false ကို Return ပြန်မှာ ဖြစ်ပါတယ်။
IOException ကို ဖြစ်ပေါ်စေနိုင်တဲ့အတွက် Handle လုပ်ပေးဖို့လိုအပ်ပါတယ်။
mkdir() boolean

File Object မှာ သတ်မှတ်ထားတဲ့ Abstract Path Name ဖြင့် Directory ကို တည်ဆောက်ပေးမှာ ဖြစ်ပါတယ်။ တည်ဆောက်နိုင်ခဲ့ရင် true ကို Return ပြန်မှာ ဖြစ်ပြီး မတည်ဆောက်နိုင်ခဲ့ပါက false ကို Return ပြန်မှာ ဖြစ်ပါတယ်
mkdirs() boolean

File Object မှာ သတ်မှတ်ထားတဲ့ Abstract Path Name ဖြင့် Directory ကို တည်ဆောက်ပေးမှာ ဖြစ်ပါတယ်။ Child Directories တွေပါလာရင်တော့ ဒီ Method ကို အသုံးပြုရမှာ ဖြစ်ပါတယ်။ တည်ဆောက်နိုင်ခဲ့ရင် true ကို Return ပြန်မှာ ဖြစ်ပြီး မတည်ဆောက်နိုင်ခဲ့ပါက false ကို Return ပြန်မှာ ဖြစ်ပါတယ်
delete() boolean

File Object ဖြင့် ကိုယ်စားပြုသော File Directory ကို delete လုပ်လိုတဲ့အခါမှာ အသုံးပြုနိုင်ပါတယ်။ အောင်မြင်စွာ ပြီးဆုံးပါက true ကို Return ပြန်မှာ ဖြစ်ပြီး မဖျက်နိုင်ခဲ့ပါက false ကို Return ပြန်မှာ ဖြစ်ပါတယ်။
deleteOnExit() void

File Object ကို JVM ကနေ Application ကို Run တာပြီးတဲ့ အချိန်မှာ Delete လုပ်ပေးမှာ ဖြစ်ပါတယ်။ Return Type တော့မရှိပါဘူး။

import java.io.*;

public class FileTest {

    public static void main(String[] args) throws IOException{
        
        File file = new File("Test.txt");
        boolean result1 = file.createNewFile();

        System.out.println(result1 ? "Success" : "Fails");

        File dir1 = new File("outer");
        File dir2 = new File(dir1, "inner");

        dir1.mkdirs();

        boolean result2 = dir1.delete();
        System.out.println(result2 ? "Success" : "Fails");
    }
}



About Path Information

Path လမ်းကြောင်းနဲ့ပတ်သက်ပြီး အောက်ပါ Method များကို အသုံးပြုနိုင်ပါတယ်။

Method Return Type Description
getAbsoluteFile() File

Absolute Path ပုံစံနဲ့ တည်ဆောက်ထားတဲ့ File Object ကို ရရှိမှာ ဖြစ်ပါတယ်။
getAbsolutePath() String

File Object ရဲ့ Absolute Path ကို ရရှိမှာ ဖြစ်ပါတယ်
getCanonicalFile() File

Canonical ပုံစံဖြင့်တည်ဆောက်ထားတဲ့ File Object ကို ရရှိမှာ ဖြစ်ပါတယ်
getCanonicalPath() String

Absolute and Unique ဖြစ်တဲ့ Canonical File Path ကို ရရှိမှာ ဖြစ်ပါတယ်
getName() String

File Name ကို ရရှိမှာ ဖြစ်ပါတယ်။
getParent() String

Parent Directory ရဲ့ Name ကို ရရှိမှာ ဖြစ်ပါတယ်။ တကယ်လို့ သတ်မှတ်ထားခြင်း မရှိပါက null ကို ပြန်ရမှာ ဖြစ်ပါတယ်။
getParentFile() File

Parent Directory ရဲ့ File Object ကို ပြန်ရမှာဖြစ်ပါတယ်။ သတ်မှတ်ထားခြင်းမရှိပါက null ကို ပြန်ရမှာ ဖြစ်ပါတယ်။
getPath() String

Absolute Path Name ကို Return အနေနဲ့ ပြန်လည် ရရှိမှာ ဖြစ်ပါတယ်။
isAbsolute() boolean

File Object ကို သတ်မှတ်ထားတဲ့ File Name ဟာ Absolute Path ဟုတ်မဟုတ်ကို စစ်ဆေးနိုင်တဲ့ Method ဖြစ်ပါတယ်။
renameTo(File dest) boolean

လက်ရှိ File Object ကို Parameter ထဲက File အဖြစ်ပြောင်းလဲနိုင်တဲ့ Method တစ်ခုဖြစ်ပါတယ်။ File အမည် ပြောင်းတဲ့ နေရာမှာလဲ အသုံးဝင်သလို File တစ်ခုကနေ တစ်ခုကို ပြောင်းရွှေ့တဲ့နေရာမှာလဲ အသုံးဝင်ပါတယ်။

import java.io.*;

public class MoveFile {

    public static void main(String[] args) throws Exception {
        File f1 = new File("file1.txt");
        f1.createNewFile();

        File f2 = new File("dir");
        f2.mkdir();

        File f3 = new File(f2, "file2.txt");
        f1.renameTo(f3);
    }

}


Using Metadata


Method Return Type Description
isDirectory() boolean

Directory တစ်ခု ဟုတ်မဟုတ်ကို သိရှိစေနိုင်သော Method ဖြစ်ပါတယ်
isFile() boolean

File တစ်ခု ဟုတ်မဟုတ်ကို သိရှိစေနိုင်သော Method ဖြစ်ပါတယ်
isHidden() boolean

Hidden File တစ်ခု ဟုတ်မဟုတ်ကို သိရှိစေနိုင်သော Method ဖြစ်ပါတယ်
lastModified() long

နောက်ဆုံး Modified လုပ်သွားသော အချိန်ကို သိရှိစေနိုင်သော Method ဖြစ်ပါတယ်
getTotalSpace() long

File Name နဲ့သတ်မှတ်ထားတဲ့ Partition ရဲ့ ပမာဏကို သိရှိစေနိုင်သော Method ဖြစ်ပါတယ်
getFreeSpace() long

File Name နဲ့သတ်မှတ်ထားတဲ့ Partition ထဲမှာရှိတဲ့ Free Space ကို သိရှိစေနိုင်သော Method ဖြစ်ပါတယ်
getUsableSpace() long

File Name နဲ့သတ်မှတ်ထားတဲ့ Partition ထဲမှာရှိတဲ့ အသုံးပြုနိုင်သော ပမာဏကို သိရှိစေနိုင်သော Method ဖြစ်ပါတယ်
setLastModified(long time) boolean

နောက်ဆုံး Modified လုပ်တဲ့အချိန်ကို သတ်မှတ်ပေးနိုင်သော Method ဖြစ်ပါတယ်
setExcutable(boolean executable) boolean

Program တစ်ခုအနေနဲ့ Run လို့ရမရကို သတ်မှတ်ပေးနိုင်သော Method ဖြစ်ပါတယ်
setExcutable(boolean executable, boolean ownerOnly) boolean

Program တစ်ခုအနေနဲ့ Run လို့ရမရကို File Owner တစ်ယောက်ထဲ လုပ်လို့ရတာလား ဆိုတဲ့ အချက်ကိုပါ သတ်မှတ်ပေးနိုင်သော Method ဖြစ်ပါတယ်
setReadable(boolean readable) boolean

File ကို Read လုပ်လို့ရမရကိုသတ်မှတ်ပေးနိုင်သော Methodဖြစ်ပါတယ်
setReadable(boolean readable, boolean ownerOnly) boolean

File ကို Read လုပ်လို့ရမရကို File Owner တစ်ယောက်ထဲ လုပ်လို့ရတာလား ဆိုတဲ့ အချက်ကိုပါ သတ်မှတ်ပေးနိုင်သော Method ဖြစ်ပါတယ်
setReadOnly() boolean

Read Only File အဖြစ်သတ်မှတ်ပေးနိုင်သော Method ဖြစ်ပါတယ်။
setWritable(boolean writable) boolean

Write လုပ်လို့ရမရကို သတ်မှတ်ပေးနိုင်သော Method ဖြစ်ပါတယ်။
setWritable(boolean writable, boolean ownerOnly) boolean
Write လုပ်လို့ရမရကို File Owner တစ်ယောက်ထဲ လုပ်လို့ရတာလား ဆိုတဲ့ အချက်ကိုပါ သတ်မှတ်ပေးနိုင်သော Method ဖြစ်ပါတယ်


Methods for Directory

အောက်ပါ  Method တွေကတော့ File Object ဟာ Directory တစ်ခုဖြစ်မှသာ အသုံးပြုနိုင်မည့် Method တွေ ဖြစ်ပါတယ်။

Method Return Type Description
list() String[]

လက်ရှိ Directory အောက်မှာရှိတဲ့ File တွေ Directory တွေရဲ့ အမည်ကို String [] အနေနဲ့ ပြန်လည် ရရှိမှာ ဖြစ်ပါတယ်။
list(FileNameFilter filter) String[]

လက်ရှိ Directory အောက်မှာရှိတဲ့ File တွေရဲ့ Directory တွေရဲ့ အမည်ကို FileNameFilter Interface Object ကို သုံးပြီး Filter လုပ်ပြီး ပြန်လည်ရရှိနိုင်မှာ ဖြစ်ပါတယ်
listFiles() File[]

လက်ရှိ Directory အောက်မှာရှိတဲ့ File တွေ Directory တွေကို File[] အနေနဲ့ ပြန်လည် ရရှိမှာ ဖြစ်ပါတယ်။
listFiles(FileNameFilter filter) File[]

လက်ရှိ Directory အောက်မှာရှိတဲ့ File တွေ Directory တွေကို FileNameFilter Interface Object ကို သုံးပြီး Filter လုပ်ပြီး ပြန်လည်ရရှိနိုင်မှာ ဖြစ်ပါတယ်
listFiles(FileFilter filter) File[]

လက်ရှိ Directory အောက်မှာရှိတဲ့ File တွေ Directory တွေကို FileFilter Interface Object ကို သုံးပြီး Filter လုပ်ပြီး ပြန်လည်ရရှိနိုင်မှာ ဖြစ်ပါတယ်

ဒီတစ်ခေါက်တော့ Directory ထဲမှာရှိတဲ့ File တွေကို နာမည်တစ်ခုနဲ့ ရှာပြီး ဖျက်တဲ့ နမူနာတစ်ခု ရေးကြည့်ပါမယ်။ Maven ကို သုံးပြီး Library တွေကို Download လုပ်တဲ့အခါမှာ Connection မကောင်းရင် LastUpdate ဆိုတဲ့နာမည်နဲ့ File တွေကို ချန်ထားပြီး ရပ်သွားတတ်ပါတယ်။ အဲ့ဒီ File တွေကို ရှာပြီး Delete လုပ်ပေးနိုင်တဲ့ နမူနာ တစ်ခုကို ရေးကြည့်ပါမယ်။
import java.io.File;

public class MavenDelete {
    
    public static void main(String[] args) {
        String userHome = System.getProperty("user.home");
        File maven = new File(userHome, ".m2");
        File mavenRepo = new File(maven, "repository");
        deleteFiles(mavenRepo);
    }
    
    static void deleteFiles(File file) {
        if(file.isDirectory()) {
            File [] files = file.listFiles(f -> f.isDirectory() || f.getName().endsWith("lastUpdate"));
            for(File f : files) {
                deleteFiles(f);
            }
        } else {
            file.delete();
        }
    }
}

အထက်ပါ နမူနာထဲမှာတော့ mavenRepo file ကို deleteFiles method ကို သုံးပြီး ဖျက်ခိုင်းပါတယ်။ တကယ်လို့ file Object ဟာ directory ဖြစ်ရင် အဲ့ဒီ​ Directory ထဲက Directory တွေနဲ့ lastUpdate နဲ့ ဆုံးရင် ရယူလာအောင် FileFilter နေရာကို Lambda Expression နဲ့ Filter လုပ်ထားပါတယ်။ရလာတဲ့ File တွေကို Loop ပတ်ပြီး
deleteFile ကို ပြန်ခေါ်ခိုင်းပါတယ်။

တကယ်လို့ Directory ဆိုရင် အောက်မှာ ရှိတဲ့ File တွေကို ရှာပြီး deleteFile ကို ပြန်ခေါ်ပါလိမ့်မယ်။ Directory မဟုတ်ပဲ File တွေဖြစ်နေလို့ကတော့ lastUpdate နဲ့ ဆုံးနေမှာ ဖြစ်တဲ့အတွက် delete လုပ်သွားပါမယ်။


Switch Other Types


Method Return Type Description
toPath() Path

Java NiO2 ရဲ့ Path Object အဖြစ်ပြောင်းပေးနိုင်တဲ့ Method ဖြစ်ပါတယ်
toStirng() String

File Object ရဲ့ Path Name ကို ရရှိနိုင်မှာ ဖြစ်ပါတယ်။ getPath method နှင့် ရလဒ်ခြင်း အတူတူဖြစ်ပါတယ်
toURI() URI

File Path Name ကို ကိုယ်စားပြုသော URI Object ကို ပြန်လည်ရရှိမှာ ဖြစ်ပါတယ်

File Object ဟာ Java IO ကို အသုံးပြုရာမှာ မရှိမဖြစ်လိုအပ်သော Object တစ်ခုဖြစ်ပါတယ်။ လက်ရှိ File တွေ Directory တွေရဲ့ Abstract Path Name ကို ကိုယ်စားပြုတဲ့ Object တစ်ခုဖြစ်ပါတယ်။ File Object တစ်ခုကို ဘယ်လို Create လုပ်မယ်။ File တွေ Directory တွေကို ဘယ်လို တည်ဆောက်မယ်၊ ပြီးရင် Delete လုပ်မယ်။ Directory ထဲမှာရှိတဲ့ File တွေကို ဘယ်လို ရှာဖွေမယ်ဆိုတာကို သိရှိထားအောင် လေ့လာထားဖို့ လိုအပ်ပါမယ်။

ဆက်ပါဦးမယ်
မင်းလွင်