February 23, 2014

Project Coin

ယနေ့မှာတော့ ပရိုဂရမ်မာ တစ်ယောက်အနေဖြင့် Java 7 ၏ ဘာသာရပ်ပိုင်းဆိုင်ရာ ပြောင်းလည်းမှု့ကို ဆက်လက် လေ့လာ ဖော်ပြသွားပါမည်။ ယနေ့ ဖော်ပြသွားမည့် အကြောင်းမှာမှာ ယခု Java 7 တွင် ပါဝင်ခဲ့သော Project Coin ၏ ပြုပြင်ပြောင်းလည်းမှု့များပဲဖြစ်ပါသည်။ ဒီ Project Coin အကြောင်းကို ပြီးခဲ့တဲ့နှစ်က မြန်မာအိုင်တီပရိုတွင် Open JDK 7 ကိ သုံး၍ ဖော်ပြခဲ့ဘူးပါသည်။ ယခုတော့ JDK 1.7 လည်း တရားဝင် ထုတ်ပြန်ခဲ့ပြီးဖြစ်ပြီး၊ Eclipse မှာလည်း Java 7 ကို တရားဝင် Support လုပ်လာပြီဖြစ်၏။ JDK 1.7 နှင့် Eclipse ကို သုံးပြီး Project Coin ကို ပြန်ပြီး လေ့လာပါဦးမည်။
Project Coin ဆိုသည်မှာ အမည်အတိုင်း အကြွေစေ့၊ အသေးသုံး ဆိုသလို ဘာသာရပ်ပိုင်းဆိုင်ရာ အသေးသုံးပြောင်းလည်းမှု့ များကို ရေးသားနေသော ပရိုဂျက်တစ်ခုဖြစ်ပါသည်။

Java 6 အရောက်တွင် ဘာသာရပ်ဆိုင်ရာ ပြောင်းလည်းမှု့မှာ သိပ်ပြီးထူးခြားမှု့ မရှိခဲ့သော်လည်း၊ Java 7 အရောက်မှာတော့ အတော်လေးကို ပြောင်းလည်းလာသည်ကိုတွေ့ရ၏။ သို့ရာတွင် Java 5 ၏ Generics နှင့် Anotation များကဲ့သို့လည်း ထင်ရှားလောက်သော ပြောင်းလည်းမှု့ များတော့ မဟုတ်ပါ။ သို့ရာတွင် ဤတစ်ခေါက် ပြောင်းလည်းမှု့များသည် ပရိုဂရမ်မာ တစ်ယောက်အနေဖြင့် အသုံးဝင်သော ပြောင်းလည်းမှု့များကို တွေ့ရပါသဖြင့် လွန်စွာမှ အားရမိပါသည်။


switch ဝါကျတွင် String ကို အသုံးပြုလာနိုင်ခြင်း

Java 7 မတိုင်ခင်တွင် switch ဝါကျ၌ byte, char, int, shot များနှင့် ၎င်း၏ Wrapper Class များကိုသာ အသုံးပြုနိုင်ခဲ့၏။ သို့ရာတွင် Java 7 အရောက်တွင် switch ဝါကျ၌ String များကိုပါ အသုံးပြုလာ နိုင်ပါသည်။
public class SwitchSample {

 /**
  * @param args
  */
 public static void main(String[] args) {
  writeChar("one");
  writeChar("two");
  writeChar("four");
 }

 static void writeChar(String str) {
  switch (str) {
  case "one":
   System.out.println("One is comming");
   break;
  case "two":
   System.out.println("Two is comming");
   break;
  case "three":
   System.out.println("Three is comming");
   break;
  default:
   System.out.println(str + " is comming");
   break;

  }
 }

}
အထက်ပါ ကုဒ်များအတိုင်း String များဖြင့် လုပ်ဆောင်ချက်များကို ခွဲခြား၍ ရေးသားနိုင်မည် ဖြစ်၏။ သို့ရာတွင် String ကိန်းရှင်သည် null ဖြစ်ပါက NullPointerException ကို ဖြစ်ပွားစေနိုင်ပါသဖြင့် ကရုပြုစေလိုပါသည်။ အကြောင်းမှာ switch ဝါကျ၏ ပြောင်းလည်းမှု့သည် JVM အဆင့် ပြောင်းလည်းခြင်း မဟုတ်သောကြောင့် ဖြစ်၏။ ကွန်ပိုင်း လုပ်စဉ် ပြောင်းလည်းပေးခြင်း ဖြစ်သောကြောင့် ဖြစ်ပါသည်။ 

ကွန်ပိုင်းလာက ဘယ်လို ပြင်ရေးထားတယ်ဆိုတာကို Class Editor ကို သုံးပြီး ဖွင့်ကြည့်ပါမည်။
// Compiled from SwitchSample.java (version 1.7 : 51.0, super bit)
public class com.mmjug.java7.ep1.SwitchSample {
  
  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  public SwitchSample();
    0  aload_0 [this]
    1  invokespecial java.lang.Object() [8]
    4  return
      Line numbers:
        [pc: 0, line: 3]
      Local variable table:
        [pc: 0, pc: 5] local: this index: 0 type: com.mmjug.java7.ep1.SwitchSample
  
  // Method descriptor #15 ([Ljava/lang/String;)V
  // Stack: 1, Locals: 1
  public static void main(java.lang.String[] args);
     0  ldc <String "one"> [16]
     2  invokestatic com.mmjug.java7.ep1.SwitchSample.writeChar(java.lang.String) : void [18]
     5  ldc <String "two"> [22]
     7  invokestatic com.mmjug.java7.ep1.SwitchSample.writeChar(java.lang.String) : void [18]
    10  ldc <String "four"> [24]
    12  invokestatic com.mmjug.java7.ep1.SwitchSample.writeChar(java.lang.String) : void [18]
    15  return
      Line numbers:
        [pc: 0, line: 9]
        [pc: 5, line: 10]
        [pc: 10, line: 11]
        [pc: 15, line: 12]
      Local variable table:
        [pc: 0, pc: 16] local: args index: 0 type: java.lang.String[]
  
  // Method descriptor #21 (Ljava/lang/String;)V
  // Stack: 4, Locals: 2
  static void writeChar(java.lang.String str);
      0  aload_0 [str]
      1  dup
      2  astore_1
      3  invokevirtual java.lang.String.hashCode() : int [28]
      6  lookupswitch default: 109
          case 110182: 40
          case 115276: 52
          case 110339486: 64
     40  aload_1
     41  ldc <String "one"> [16]
     43  invokevirtual java.lang.String.equals(java.lang.Object) : boolean [34]
     46  ifne 76
     49  goto 109
     52  aload_1
     53  ldc <String "two"> [22]
     55  invokevirtual java.lang.String.equals(java.lang.Object) : boolean [34]
     58  ifne 87
     61  goto 109
     64  aload_1
     65  ldc <String "three"> [38]
     67  invokevirtual java.lang.String.equals(java.lang.Object) : boolean [34]
     70  ifne 98
     73  goto 109
     76  getstatic java.lang.System.out : java.io.PrintStream [40]
     79  ldc <String "One is comming"> [46]
     81  invokevirtual java.io.PrintStream.println(java.lang.String) : void [48]
     84  goto 134
     87  getstatic java.lang.System.out : java.io.PrintStream [40]
     90  ldc <String "Two is comming"> [53]
     92  invokevirtual java.io.PrintStream.println(java.lang.String) : void [48]
     95  goto 134
     98  getstatic java.lang.System.out : java.io.PrintStream [40]
    101  ldc <String "Three is comming"> [55]
    103  invokevirtual java.io.PrintStream.println(java.lang.String) : void [48]
    106  goto 134
    109  getstatic java.lang.System.out : java.io.PrintStream [40]
    112  new java.lang.StringBuilder [57]
    115  dup
    116  aload_0 [str]
    117  invokestatic java.lang.String.valueOf(java.lang.Object) : java.lang.String [59]
    120  invokespecial java.lang.StringBuilder(java.lang.String) [63]
    123  ldc <String " is comming"> [65]
    125  invokevirtual java.lang.StringBuilder.append(java.lang.String) : java.lang.StringBuilder [67]
    128  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [71]
    131  invokevirtual java.io.PrintStream.println(java.lang.String) : void [48]
    134  return
      Line numbers:
        [pc: 0, line: 15]
        [pc: 76, line: 17]
        [pc: 84, line: 18]
        [pc: 87, line: 20]
        [pc: 95, line: 21]
        [pc: 98, line: 23]
        [pc: 106, line: 24]
        [pc: 109, line: 26]
        [pc: 134, line: 30]
      Local variable table:
        [pc: 0, pc: 135] local: str index: 0 type: java.lang.String
      Stack map table: number of frames 8
        [pc: 40, append: {java.lang.String}]
        [pc: 52, same]
        [pc: 64, same]
        [pc: 76, same]
        [pc: 87, same]
        [pc: 98, same]
        [pc: 109, same]
        [pc: 134, chop 1 local(s)]
}
အဓိက Switch ဝါကျထဲမှာ ဘယ်လိုရေးထားလဲဆိုတာကို ကြည့်ကြည့်ပါမည်။ အဝါရောင်စာလုံးဖြင့် ရေးသားထားသည်ကို ကြည့်ပါ။ ကွန်ပိုင်းလာက String ကို hash အနေဖြင့်ပြောင်းလည်း ပြီးအသုံးပြုသည်ကို တွေ့ရပါမည်။ အကယ်၍ "one" ဆိုပါက switch ဝါကျအတွင်းတွင် "one" ၏ hashCode ဖြစ်သော case 110182: 40 စာကြောင်းကို ရောက်ရှိပြီး စာကြောင်းနံပါတ် ၄၀ ကို သွားမည် ဖြစ်ပါသည်။ အကယ်၍ စာကြောင်းသည် one ဖြစ်ပါက စာကြောင်းနံပါတ် ၇၆ ကို ဆက်သွားပါမည်။ မဟုတ်ပါက စာကြောင်း ၁၀၉ကိုသွားပါမည်။

စာကြောင်းနံပါတ် ၇၆ကိုကြည့်ပါ။ "one is comming" ဆိုတဲ့ စာကြောင်းကို ရေးသားစေပြီး၊ နောက်ဆုံးတွင် စာကြောင်း ၁၃၄ကိုသွားပြီး return လုပ်နေပါသည်။

အားလုံးကို ခြုံပြီး ကြည့်မည်ဆိုပါက String ကို hashCode အနေနဲ့ပြောင်းပြီး Switch လုပ်ပါသည်။ ပြီးမှ တဆင့်ချင်း if else ဖြင့် လမ်းများကို ခွဲခြားအလုပ်လုပ်စေခြင်းသာဖြစ်၏။ ကွန်ပိုင်းလာမှ တဆင့်ပြောင်းပြီး String များကို Switch လုပ်နိုင်အောင် ဖန်တီးပေးနေခြင်းသာဖြစ်၏။ တကယ်တမ်းကျတော့ int ကိုသာ Switch လုပ်နေသည်ကို တွေ့ရပါသည်။ ထို့အတွက် အသုံးပြုမည့် String သည် null ဖြစ်နေပါက၊ String အား hashCode ကို ပြောင်းချိန်မှာ NullPointerException နဲ့တွေ့ရမည် ဆိုသည်ကို သိရှိနိုင်ပါသည်။


ကိန်းဂဏာန်းများအား ဖော်ပြပုံပြောင်းလည်းမှု့

Java ဘာသာရပ်တွင်လည်း C ကဲ့သို့ပင် ကိန်းဂဏာန်းများ၏ ရှေ့တွင် 0 ကိုဖြည့်ရေးပါက၊ octal digit အဖြစ်၎င်း၊ 0x ကို ဖြည့်ရေးပါက hexadecimal အဖြစ်၎င်း သတ်မှတ်ရေးသားနိုင်ပါသည်။ သို့ရာတွင် အသုံးများသော binary Digit များအတွက်မှာမူ ရေးသားနိုင်ခြင်းမရှိခဲ့ပေ။

Java 7 အရောက်တွင် Binary Digit များအား အပြည့်ကိန်းများ၏ အရှေ့တွင် 0b သို့မဟုတ် 0B ကိုရေးသားပြီး ဖော်ပြလာနိုင်ခဲ့ပါသည်။ ထို့အပြင် အပြည့်ကိန်းများအကြားတွင် "_" ကို ဖြည့်ရေး လာနိုင်ပါသည်။
package com.mmjug.java7.ep1;

public class NewLiteralSample {
 
 public static void main(String[] args) {
  int a = 4;
  int b = 0b100;
  System.out.println("a == b : " + (a == b));
  
  a+=1_000_000;
  System.out.println(a);
 }
}
အထက်ဖော်ပြပါအတိုင်း 0b100သည် အပြည့်ကိန်း 4 ကို ဖော်ပြနေပြီး၊ စာကြောင်း ၈ကြောင်းမြောက်တွင် a == b ၏ တန်ဖိုးကို ရေးသားစေပါသည်။ a သည်လည်း 4 ဖြစ်၍ b သည်လည်း ဘိုင်နရီပုံစံဖြင့်ဖော်ပြထားသော 4 ဖြစ်ပါသောကြောင့် ဖော်ပြပုံမှန်ကန်ပါသဖြင့် ရလဒ်မှာ true ဖြစ်ပါလိမ့်မည်။ တဖန် စာကြောင်း ၁၀ တွင် a အား a နှင့် 1_000_000 အား ပေါင်း၍ အစားထိုးနေပါသည်။ "_" ကို အသုံးပြုခြင်းအားဖြင့် 1 ၏ နောက်တွင် သုညခြောက်လုံးပါသည်ကို ရှင်းလင်းစွာ မြင်နိုင်ပါသည်။ တန်ဖိုးမှာ 4 + 1000000 ဖြစ်သောကြောင့် 1000004 ဟု အဖြေထွက်ပါလိမ့်မည်။
a == b : true
1000004
တဖန် ကွန်ပိုင်းလုပ်ပြီးသော ဘိုက်ကုဒ်များအား လေ့လာကြည့်ပါမည်။
// Compiled from NewLiterialSample.java (version 1.7 : 51.0, super bit)
public class com.mmjug.java7.ep1.NewLiterialSample {
  
  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  public NewLiterialSample();
    0  aload_0 [this]
    1  invokespecial java.lang.Object() [8]
    4  return
      Line numbers:
        [pc: 0, line: 3]
      Local variable table:
        [pc: 0, pc: 5] local: this index: 0 type: com.mmjug.java7.ep1.NewLiterialSample
  
  // Method descriptor #15 ([Ljava/lang/String;)V
  // Stack: 4, Locals: 3
  public static void main(java.lang.String[] args);
     0  iconst_4
     1  istore_1 [a]
     2  iconst_4
     3  istore_2 [b]
     4  getstatic java.lang.System.out : java.io.PrintStream [16]
     7  new java.lang.StringBuilder [22]
    10  dup
    11  ldc <String "a == b : "> [24]
    13  invokespecial java.lang.StringBuilder(java.lang.String) [26]
    16  iload_1 [a]
    17  iload_2 [b]
    18  if_icmpne 25
    21  iconst_1
    22  goto 26
    25  iconst_0
    26  invokevirtual java.lang.StringBuilder.append(boolean) : java.lang.StringBuilder [29]
    29  invokevirtual java.lang.StringBuilder.toString() : java.lang.String [33]
    32  invokevirtual java.io.PrintStream.println(java.lang.String) : void [37]
    35  iload_1 [a]
    36  ldc <Integer 1000000> [42]
    38  iadd
    39  istore_1 [a]
    40  getstatic java.lang.System.out : java.io.PrintStream [16]
    43  iload_1 [a]
    44  invokevirtual java.io.PrintStream.println(int) : void [43]
    47  return
      Line numbers:
        [pc: 0, line: 6]
        [pc: 2, line: 7]
        [pc: 4, line: 8]
        [pc: 35, line: 10]
        [pc: 40, line: 11]
        [pc: 47, line: 12]
      Local variable table:
        [pc: 0, pc: 48] local: args index: 0 type: java.lang.String[]
        [pc: 2, pc: 48] local: a index: 1 type: int
        [pc: 4, pc: 48] local: b index: 2 type: int
      Stack map table: number of frames 2
        [pc: 25, full, stack: {java.io.PrintStream, java.lang.StringBuilder}, locals: {java.lang.String[], int, int}]
        [pc: 26, full, stack: {java.io.PrintStream, java.lang.StringBuilder, int}, locals: {java.lang.String[], int, int}]
}
main မက်သတ်၏ စာကြောင်းနံပါတ် 0 နှင့် 2 ကို ကြည့်ပါ။ စာကြောင်း ၀ တွင် 4 ၏ ဖော်ပြပုံဖြစ်ပြီး၊ စာကြောင်း ၂ တွင် 0b100 အား ဖော်ပြထားခြင်းဖြစ်သည်။ Source ကုဒ်များတွင် တစ်မျိုးစီ ရေးထားသား သော်လည်း ကွန်ပိုင်း လုပ်ပြီးသောအခါ အတူတူပင်ဖြစ်သည်။ ထို့အပြင် စာကြောင်းနံပါတ် ၃၆ ကို ကြည့်ပါ။ 1_000_000 ဖြင့်ရေးသားထားသည်ကို 1000000 ဟု ပြောင်းလည်းပေးပါသည်။ ဤအချက်ကို ကြည့်ခြင်းအားဖြင့် ဤပြောင်းလည်းမှု့သည် JVM အဆင့်ပြောင်းလည်းမှု့မဟုတ်ပဲ ကွန်ပိုင်းလာ အဆင့်တွင် ပြောင်းလည်းပေးမှု့ ဆိုသည်ကို သိရှိနိုင်ပါသည်။


Generics များအား အတိုကောက် ရေးသားခြင်း

Java 5 မှစတင် အသုံးပြုလာနိုင်သော Generics များသည် Java ဘာသာရပ်၏ Collection များနှင့် နေရာအမျိုးမျိုးတွင် အသုံးပြုလာခဲ့ကြ၏။ Generics အား အသုံးပြုခြင်း အားဖြင့် မလိုအပ်သော ပုံစံပြောင်းခြင်း (Cast) အား လျှော့ပါးစေပါသည်။ သို့ရာတွင် Generics အားအသုံးပြုရာတွင် Object အားသတ်မှတ်သည့် ဘယ်ဘက်တွင်၎င်း၊ ညာဘက်ရှိ Constructor ကို ရေးသားရာတွင်၎င်း Generics ၏ ပါရာမီတာကို ရေးသားရန် လိုအပ်ခဲ့သည်။
aimport java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class GenericsSaple {

 List<String> strList = new ArrayList<String>();
 List<Map<String, List<String>>> mapList = new ArrayList<Map<String, List<String>>>();
}
အထက်ပါ Java 5 တွင် ရေးသားပုံကို ကြည့်ပါ။ ပါရာမီတာများလာပါက ပို၍ ရှုပ်ထွေးလာပါသည်။ Java 7 အရောက်တွင် ညာဘက် Constructor ၏ ပါရာမီတာများကို ရေးသားစရာမလိုအပ်တော့ပေ။ <> ဟု ရေးသားရုံနှင့် အသုံးပြုလာ နိုင်ပါသည်။ <> ရေးသားပုံအား Diamond သင်္ကေတဟုလည်း ခေါ်ပါသေးသည်။

အထက်ပါ ကုဒ်များကို Java 7 ရေးသားပုံဖြင့် ပြန်လည် ရေးသားကြည့်ပါမည်။
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class GenericsSaple {

 List<String> strList = new ArrayList<>();
 List<Map<String, List<String>>> mapList = new ArrayList<>();
}
နှစ်မျိုး ယှဉ်ကြည့်ပါမှ မည်မျှအမြင် ရှင်းလာသည်ကို သိရှိနိုင်ပါသည်။ Java 7 အရောက်တွင် Object ကို ဖော်ပြသည့် ဘက်တွင် Generics ၏ ပါရာမီတာကို ရေးသားထားပါက၊ Constructor ဘက်တွင် လိုအပ်သော ပါရာမီတာများကို ကွန်ပိုင်းလာမှ ဖြည့်စွက် နိုင်ပါသည်။

သို့ရာတွင် အောက်ပါအတိုင်းရေးသားထားသော ကုဒ်များအား ကွန်ပိုင်းလုပ်ကြည့်သောအခါ Error ဖြစ်မည် ဖြစ်ပါသည်။
package com.mmjug.java7.ep1;

public class GenericsSaple {

 class Box<T> {
  private T value;
  
  public Box(T t) {
   this.value = t;
  }
  
  public T getValue() {
   return this.value;
  }
 }
 
 public static void main(String[] args) {
  Box<Number> box = new Box<>(30);
 }
}

စာကြောင်း ၁၈ကြောင်းမြောက်တွင် အင်းစတန့်စ်အား ပြုလုပ်သည့်နေရာတွင် ကွန်ပိုင်း အယ်ရာ ဖြစ်ပါလိမ့်မည်။ 30 အား Autoboxing ဖြင့် Object အဖြစ်ပြောင်းလည်းရာတွင် Integer ကို ပြောင်းလည်းမည် ဖြစ်သောကြောင့် Number နေရာတွင် အစားထိုး၍မရသောကြောင့် ဖြစ်ပါသည်။

ကွန်ပိုင်း လုပ်ထားသော Class ဖိုင်အား ဖွင့်ကြည့်ပါမည်။
// Compiled from GenericsSaple.java (version 1.7 : 51.0, super bit)
public class com.mmjug.java7.ep1.GenericsSaple {
  
  // Method descriptor #6 ()V
  // Stack: 1, Locals: 1
  public GenericsSaple();
    0  aload_0 [this]
    1  invokespecial java.lang.Object() [8]
    4  return
      Line numbers:
        [pc: 0, line: 3]
      Local variable table:
        [pc: 0, pc: 5] local: this index: 0 type: com.mmjug.java7.ep1.GenericsSaple
  
  // Method descriptor #15 ([Ljava/lang/String;)V
  // Stack: 3, Locals: 1
  public static void main(java.lang.String[] arg0);
     0  new java.lang.Error [16]
     3  dup
     4  ldc <String "Unresolved compilation problem: \n\tType mismatch: cannot convert from GenericsSaple.Box<Integer> to GenericsSaple.Box<Number>\n"> [18]
     6  invokespecial java.lang.Error(java.lang.String) [20]
     9  athrow
      Line numbers:
        [pc: 0, line: 18]

  Inner classes:
    [inner class info: #26 com/mmjug/java7/ep1/GenericsSaple$Box, outer class info: #1 com/mmjug/java7/ep1/GenericsSaple
     inner name: #28 Box, accessflags: 0 default]
}
main method ၏ နံပါတ် ၄ တွင် Error Message ကို ကြည့်ရင် Box ၏ နေရာတွင် Box ကို အစားထိုးနေသည်ကို ဖော်ပြနေပါသည်။

ယခင် တစ်ခေါက်ရေးသားဘူးသည့် အကြောင်းဖြစ်သောကြောင့် Project Coin အား အကျဉ်းချုပ်၍ တစ်ကြိမ်တည်းနှင့် ပြီးအောင်ရေးရန် စဉ်းစားထားသော်လည်း၊ ရေးရင်းနဲ့ အတော်လေးကို ရှည်လာပါသဖြင့် ဤတစ်ကြိမ်တွင် ဤနေရာတွင် ခေတ္တနားပါဦးမည်။ နောက်ရက်များတွင် Project Coin ၏ ပြုပြင်ပြောင်းလည်းမှု့များကို ဆက်လက်ဖော်ပြသွားပါဦးမည်။

လေးစားစွာဖြင့်
မင်းလွင်

No comments:

Post a Comment