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
လေးစားစွာဖြင့်
မင်းလွင်
No comments:
Post a Comment