Java Operators

โดย เม้ง

1. เกริ่นนำ
เจอกันอีกแล้วครับคุณผู้อ่าน ในบทความนี้ผู้เขียนจะขอพูดเกี่ยวกับจาวาโอเปอเรเตอร์ (java operator) โอเปอเรเตอร์ของจาวานั้นส่วนใหญ่จะเหมือนกับภาษา C และ C++ เพราะฉะนั้นคุณผู้อ่านที่รู้เกี่ยวกับโอเปอเรเตอร์ของ C และ C++ ก็จะอาจจะอ่านผ่านไปได้อย่างรวดเร็ว แต่ควรจะระวังว่ามีโอเปอเรเตอร์อีกหลายตัวที่จาวาได้เพิ่มเติมเข้ามาเพื่อให้เกิดความสะดวกต่อผู้เขียนโปรแกรมมากยิ่งขึ้น

2. วัตถุประสงค์
2.1 เพื่อให้คุณผู้อ่านได้รู้จักและคุ้นเคยกับโอเปอเรเตอร์ต่าง ๆ ในจาวา
2.2 เพื่อให้คุณผู้อ่านได้เรียนรู้เกี่ยวกับ operand และค่า return ของโอเปอเรเตอร์ต่างๆ

3. โอเปอเรเตอร์คืออะไร
ถ้าเราแปลกันตรง ๆ โอเปอเรตอร์นั้นหมายถึงตัวกระทำนั่นเอง คุณผู้อ่านที่ไม่เคยเรียนเกี่ยวกับภาษาคอมพิวเตอร์คงจะสงสัยว่าคำว่าตัวกระทำนี้หมายถึงอะไรและมันกระทำอะไรกันแน่ ถ้าในภาษาคอมพิวเตอร์มีแต่ตัวแปร (variable) แต่ขาดตัวกระทำแล้วล่ะก็ภาษานั้นก็จะไม่สามารถเอามาใช้ประโยชน์อะไรได้เลย คุณผู้อ่านลองคิดดูสิครับว่าถ้าเรามีแต่ตัวแปรและหน่วยความจำ (memory) แต่ไม่สามาถใส่ค่าเข้าไปในตัวแปรนั้นได้ หรือไม่สามารถบวกลบคูณหารกับมันได้ หรือไม่สามารถเช็คได้ว่าตัวแปรนั้นมีค่าเท่ากับเท่าไร เปรียบเทียบได้กับเรามีรถยนต์แต่รถคันนั้นไม่สามารถวิ่งได้ เพราะฉะนั้นโอเปอเรเตอร์นั้นเป็นส่วนสำคัญอย่างยิ่งที่ทุกภาษาต้องมีอยู่ และถ้าภาษาไหนสามารถออกแบบโอเปอเรเตอร์ให้ใช้งานได้ง่ายแล้วล่ะก็ภาษานั้นจะประสบความสำเร็จมาก

โอเปอเรเตอร์นั้นสามารถถูกแบ่งประเภทตามจำนวนตัวถูกกระทำ (operand) ได้ดังนี้คือ ตัวถูกกระทำเดี่ยว (unary operator) ตัวถูกกระทำคู่ (binary operator) และตัวถูกกระทำสามตัว (ternary operator)

unary operator นั้นคือโอเปอเรเตอร์ที่ใช้ operand เพียงแค่ตัวเดียวเพื่อให้เกิดความหมาย ยกตัวอย่างเช่น

int a = 20;
int b = -a;
int c = ++a;

โอเปอเรเตอร์ "-" ในบรรทัดที่สองนั้นจะ return ค่า -1*a หลังจากนั้นโอเปอเรเตอร์ "=" จะเอาค่าไปใส่ในตัวแปร b ส่วนโอเปอเรเตอร์ "++" ในบรรทัดที่สามนั้นจะ return ค่า a+1 แล้วโอเปอเรเตอร์ "=" จะเอาค่าไปใส่ในตัวแปร c คุณผู้อ่านจะสังเกตเห็นว่าทั้งสอง operators นั้นใช้ตัวถูกกระทำเพียงตัวเดียว ส่วน binary และ ternary operators นั้นผู้เขียนจะอธิบายในช่วงต่อๆไป

4. โอเปอเรเตอร์ต่างๆในจาวา
เราสามารถแบ่งโอเปอเรเตอร์ในจาวาออกได้เป็นหลายๆชนิด ได้แก่
4.1 โอเปอเรเตอร์ทางเรขาคณิต (Arithmatic Operator)
4.2 โอเปอเรเตอร์ที่ใช้เปรียบเทียบ (Relational Operator)
4.3 โอเปอเรเตอร์ที่เกี่ยวข้องกับบิต (Bitwise Operator)
4.4 โอเปอเรเตอร์ในการตั้งค่า (Assignment Operator)
4.5 โอเปอเรเตอร์ลอจิกหรือโอเปอเรเตอร์ทางตรรกศาสตร์ (Logical Operator)
4.6 โอเปอเรเตอร์คอนดิชันนัล (Conditional Operator)
4.7 โอเปอเรเตอร์อื่นๆ

5. โอเปอเรเตอร์ทางเรขาคณิต
โอเปอเรเตอร์ทางเรขาคณิตนั้นประกอบไปด้วยทั้ง unary และ binary โอเปอเรเตอร์

ตารางที่ 1 Unary Arithmatic Operator

unary โอเปอเรเตอร์
ค่ารีเทอร์น
+ operand
ค่าของ operand ที่อยู่ทางขวา
- operand
-1*(ค่าของ operand ที่อยู่ทางขวา)
++operand
ค่าของ operand บวกเพิ่มอีกหนึ่ง
operand++
ค่าของ operand ขณะนั้น
--operand
ค่าของ operand ลบลงหนึ่ง
operand--
ค่าของ operand ขณะนั้น

ตารางที่ 2 Binary Arithmatic Operator

binary โอเปอเรเตอร์
ค่า return
+
ค่าของ operands ทางซ้ายและทางขวาของ "+" บวกกัน
-
ค่าของ operand ทางซ้ายของ "-" หักออกด้วยค่าของ operand ทางขวา
*
ค่าของ operand ทางซ้ายของ "*" คูณด้วยค่าของ operand ทางขวา
/
ค่าของ operand ทางซ้ายของ "/" หารด้วยค่าของ operand ทางขวา
%
เศษที่เหลือจากการหารของ operand ทางซ้ายหารด้วย operand ทางขวา

เราลองมาดูตัวอย่างกันดีกว่าครับ

โปรแกรมที่ 1
1    // arithOpTest.java
2    public class arithOpTest {
3      public static void main(String args[]) {
4        int a = 11;
5        int b = 4;
6        float c = 7F;
7        float d = 10F;
8        int result_int = 0;
9        float result_float = 0F;
10
11       // Print all of the initial values first
12       System.out.println("a = " + a);
13       System.out.println("b = " + b);
14       System.out.println("c = " + c);
15       System.out.println("d = " + d);
16
17       result_int = a + b;
18       System.out.println("a + b = " + result_int);
19       result_int = a - b;
20       System.out.println("a - b = " + result_int);
21       result_int = a * b;
22       System.out.println("a * b = " + result_int);
23       result_float = a / b;
24       System.out.println("a / b = " + result_float);
25       result_int = a % b;
26       System.out.println("a % b = " + result_int);
27       result_float = a + b * c / d;
28       System.out.println("a + b * c / d = " + result_float);
29       return_int = ++a;
30       System.out.println("After ++a:  a = " + a + " return_int = " + return_int);
31       return_int = a++;
32       System.out.println("After a--:  a = " + a + " return_int = " + return_int);
33       return_float = --c;
34       System.out.println("After --c:  c = " + c + " return_float = " + return_float);
35       return_float = c--;
36       System.out.println("After c--:  c = " + c + " return_float = " + return_float);
37     }
38   }

Operator +, -, * / และ % คงจะเป็นไปตามที่คุณผู้อ่านคิด ทีนี้เราลองมาดู operator ++ และ -- กันดีกว่าครับ ในบรรทัดที่ 30 ค่า a และค่า return_value นั้นมีค่าเท่ากันและเท่ากับ 12 แต่ถ้าคุณผู้อ่านไปดูผลลัพธ์ของบรรทัดที่ 32 ค่าของ a กลับเท่ากับ 13 แต่ return_value เท่ากับ 12 สิ่งนี้แสดงให้เห็นถึงความแตกต่างของโอเปอเรเตอร์ทั้งสองครับ

จากนี้ไปผู้เขียนจะขอเรียก Operator ++ หรือ -- ที่อยู่ทางซ้ายของ operand ว่า prefix ++ หรือ prefix --, ส่วนตัวที่อยู่ทางขวาของ operand จะขอเรียกว่า suffix ++ หรือ suffix -- นะครับ ทั้ง prefix และ suffix ++ และ -- นั้นจะทำหน้าที่สองอย่างคือ return ค่าของตัวมันเองและเพิ่มหรือลดค่าของตัวมันเองหนึ่ง เพราะฉะนั้นหลังจากที่ตัวแปรได้ผ่าน operator ตัวนี้แล้วค่าที่อยู่ในตัวแปรนั้นจะต่างจากเดิมหนึ่ง ทีนี้ความแตกต่างของ prefix ++ และ suffix ++ ก็คือ prefix ++ นั้นจะเพิ่มค่าในตัวแปรก่อนแล้วจึง return แต่ suffix ++ นั้นจะ return ก่อนแล้วจึงเพิ่มค่าในตัวแปร สรุปความได้สั้นว่า prefix ++ และ -- operators นั้นจะมีผลก่อนที่จะผ่าน operator อื่น แต่ suffix ++ และ -- นั้นจะมีผลหลังจากผ่าน operator อื่น คุณผู้อ่านคงจะสามารถเดาถึง prefix -- และ suffix -- ได้เลยนะครับว่ามันทำงานเหมือนกัน เราลองมาพิจารณาดูตัวอย่างเล็ก ๆ ข้างล่างกันดีกว่าครับ

a=9;
return_int = a++*8+4;

ค่า a ซึ่งเท่ากับ 9 ได้ถูกรีเทอร์ออกมาก่อนที่จะถูก incremented เพราะฉะนั้นค่าของ return_int จึงเท่ากับ 76

คุณผู้อ่านจะเห็นได้ว่าในบรรทัดที่ 23 ผู้เขียนได้ใช้ตัวแปรแบบ float มารับค่าในการหารของ int เหตุผลก็เนื่องจากว่าผลของการหารของเลขจำนวนเต็มสองตัวนั้นสามารถเกิดเป็นเลขทศนิยมได้ เพราะฉะนั้นคุณผู้อ่านควรจะระวังตรงจุดนี้ให้ดีมิฉะนั้นคุณอาจจะสูญเสียค่าหลังจุดทศนิยมไปได้ จากผลลัพธ์หลังจากการรันโปรแกรมนี้คุณผู้อ่านคงจะเห็นคำตอบที่ผิดในบรรทัดที่ 24 ค่าของ 11/4 นั้นควรจะได้ 2.75 แต่กลับแสดงค่า 2.0 ออกมา คุณผู้อ่านคงจะสงสัยอย่างยิ่งว่าเกิดอะไรขึ้น

ในจาวานั้นเรายังมีกฎเพิ่มเติมเกี่ยวกับ Arithmatic Operators อีกว่า
สมมุติให้ X แทน Arithmatic operator ตัวใหนก็ได้ใน +, -, * และ / โดยให้ A และ B เป็นตัวแปรตัวใหนก็ได้ใน byte, short, int, long, float และ double เราลองมาดูค่า return ของ A X B กันนะครับ

ถ้า A หรือ B เป็น double

ตัวแปรตัวที่เหลือจะถูกเปลี่ยนให้เป็น double ชั่วคราวก่อนแล้วค่อยผ่าน operator เพราะฉะนั้นค่าที่ return จะเป็น double
ถ้า A หรือ B เป็น float แต่อีกตัวหนึ่งไม่ใช่ double
ตัวแปรตัวที่เหลือจะถูกเปลี่ยนให้เป็น float ชั่วคราวก่อนแล้วค่อยผ่าน operator เพราะฉะนั้นค่าที่ return จะเป็น float
ถ้า A หรือ B เป็น long แต่อีกตัวหนึ่งไม่ใช่ double หรือ float
ตัวแปรตัวที่เหลือจะถูกเปลี่ยนให้เป็น long ชั่วคราวก่อนแล้วค่อยผ่าน operator เพราะฉะนั้นค่าที่ return จะเป็น long
ถ้า A และ B ไม่ใช่ double, float หรือ long เลย
ตัวแปรทั้งสองตัวจะถูกเปลี่ยนให้เป็น int ชั่วคราวก่อนแล้วค่อยผ่าน operator เพราะฉะนั้นค่าที่ return จะเป็น int
หลังจากที่คุณผู้อ่านได้รู้กฎเหล่านี้แล้วคุณคงจะเข้าใจว่าทำไมค่าของ result_float ในบรรทัดที่ 24 จึงกลายเป็น 2.0 เนื่องจากว่าทั้ง a และ b เป็นตัวแปรแบบ int เพราะฉะนั้นการหารจึงเป็นการหารแบบ int ผลลัพธ์ก็เลยออกมาเป็น int ส่วนที่อยู่หลังจุดทศนิยมจึงหายไปถึงแม้ว่าตัวแปรที่จะมารับค่า return ของ operator นั้นจะเป็น float วิธีการแก้ไขก็คือเราต้อง cast ตัวใดตัวหนึ่งให้เป็น float เสียก่อนแล้วจึงหารกัน ถ้าเราเปลี่ยนบรรทัดที่ 23 ให้เป็น

23       result_float = (float)a / b หรือ
23       result_float = a / (float)b หรือ
23       result_float = (float)a / (float)b

ค่าของ run_float นั้นก็จะกลายเป็นผลของการหารที่ถูกต้อง

ทีนี้เราลองมาดูกันที่บรรทัดที่ 27 กันบ้างดีกว่าครับ ในระหว่าง 4 arithmatic operators นั้น operator * และ / จะถูกกระทำก่อน operator + และ - หรือพูดอีกนัยหนึ่งได้ว่า * และ / มี precedence เท่ากันและมากกว่า + และ - เพราะฉะนั้นในประโยค a + b * c / d นั้นค่า b จะถูกเอาไปคูณกับ c ก่อนแล้วเอาไปหารด้วย d แล้วจึงบวกด้วย a - ถ้าสมมุติเราอยากให้ a บวกกับ b ก่อนเราต้องใส่วงเล็บครอบ a และ b ดังใน (a + b) * c / d วงเล็บจะบังคับให้ operator ในวงเล็บถูก evaluated ก่อนอย่างอื่น แต่ถ้ามีวงเล็บหลาย ๆ อันซ้อน ๆ กันวงเล็บในสุดจะถูก evaluated ก่อน

6. โอเปอเรเตอร์ที่ใช้เปรียบเทียบ
โอเปอเรเตอร์ที่ใช้เปรียบเทียบนั้นประกอบไปด้วย ==, >, >=, <, <= และ !=
ทั้ง 6 ตัวนี้เป็น binary operators ที่ใช้เปรียบเทียบค่าตัวเลขสองค่า ส่วนใหญ่มักจะอยู่ในวงเล็บของ if, while, for หรือส่วนของโปรแกรมที่ต้องมีการเปรียบเทียบค่าที่ operator เหล่านี้ return กลับมาก็คือค่าแบบ boolean ซึ่งมีได้สองค่าคือ true หรือ false

ตารางที่ 3 โอเปอเรเตอร์ที่ใช้เปรียบเทียบ

โอเปอเรเตอร์
ความหมาย
a == b
ถ้า a มีค่าเท่ากับ b จะ return true ถ้าไม่ใช่ จะ return false
a > b
ถ้า a มีค่ามากกว่า b จะ return true ถ้าไม่ใช่ จะ return false
a >= b
ถ้า a มีค่ามากกว่าหรือเท่ากับ b จะ return true ถ้าไม่ใช่ จะ return false
a < b
ถ้า a มีค่าน้อยกว่า b จะ return true ถ้าไม่ใช่ จะ return false
a <= b
ถ้า a มีค่าน้อยกว่าหรือเท่ากับ b จะ return true ถ้าไม่ใช่ จะ return false
a != b
ถ้า a มีค่าไม่เท่ากับ b จะ return true ถ้าไม่ใช่ จะ return false

ตัวอย่างง่าย ๆ อยู่ข้างล่างนี้นะครับ

โปรแกรมที่ 2
1    // relationalOpTest.java
2    public class relationalOpTest {
3      public static void main(String args[]) {
4        int a;
5        int b = 20;     // b is always 20
6
7        a = 8;          // set a to be 8
8
9        System.out.println("a = " + a);
10       System.out.println("b = " + b);
11       if ( a > b ) {
12         System.out.println("a is greater than b");
13       }
14       if ( a >= b ) {
15         System.out.println("a is greater than and equal to b");
16       }
17       if ( a < b ) {
18         System.out.println("a is less than b");
19       }
20       if ( a <= b ) {
21         System.out.println("a is less than or equal to b");
22       }
23       if ( a == b ) {
24         System.out.println("a is equal to b");
26       }
27       if ( a != b ) {
28         System.out.println("a is not equal to b");
30       }
31
32       a = 20;          // set a to be 20
33
34       System.out.println("");
35       System.out.println("a = " + a);
36       System.out.println("b = " + b);
37       if ( a > b ) {
38         System.out.println("a is greater than b");
39       }
40       if ( a >= b ) {
41         System.out.println("a is greater than and equal to b");
42       }
43       if ( a < b ) {
44         System.out.println("a is less than b");
45       }
46       if ( a <= b ) {
47         System.out.println("a is less than or equal to b");
48       }
49       if ( a == b ) {
50         System.out.println("a is equal to b");
51       }
52       if ( a != b ) {
53         System.out.println("a is not equal to b");
54       }
55
56       a = 55;          // set a to be 55
57
58       System.out.println("");
59       System.out.println("a = " + a);
60       System.out.println("b = " + b);
61       if ( a > b ) {
62         System.out.println("a is greater than b");
63       }
64       if ( a >= b ) {
65         System.out.println("a is greater than and equal to b");
66       }
67       if ( a < b ) {
68         System.out.println("a is less than b");
69       }
70       if ( a <= b ) {
71         System.out.println("a is less than or equal to b");
72       }
73       if ( a == b ) {
74         System.out.println("a is equal to b");
75       }
76       if ( a != b ) {
77         System.out.println("a is not equal to b");
78       }
79     }
80   }

7. โอเปอเรเตอร์ที่เกี่ยวข้องกับบิต
โอเปอเรเตอร์ที่ผู้เขียนจะพูดถึงต่อไปนี้ใช้ได้แต่กับ byte, short, int และ long เท่านั้น โอเปอเรเตอร์ที่เกี่ยวข้องกับบิตนั้นประกอบไปด้วย <<, >>, &, ^, | (ขีดตั้ง) และ ~

ตารางที่ 4 โอเปอเรเตอร์ที่เกี่ยวข้องกับบิต

บิตโอเปอเรเตอร์
หน้าที่
a << b
return ค่าของ a ที่ถูกเลื่อนบิตทั้งหมดไปทางซ้ายจำนวน b บิต และเติมบิตทางขวาที่หายไปด้วยศูนย์
a >> b
return ค่าของ a ที่ถูกเลื่อนบิตทั้งหมดไปทางขวาจำนวน b บิต และเติมบิตทางซ้ายที่หายไปด้วยศูนย์
a & b
return ค่าของ a and with b บิตต่อบิต
a ^ b
return ค่าของ a exclusive or with b บิตต่อบิต
a | b
return ค่าของ a or with b บิตต่อบิต
~a
return ค่าของ one's complement ของ (int)a ถ้า a เล็กกว่าหรือเท่ากับ int

7.1 << และ >>
ทั้งสองโอเปอเตอร์นี้มีไว้สำหรับเลื่อน (shift) บิตไปทางซ้ายหรือทางขวา ตัวโอเปอเรเตอร์จะไม่เปลี่ยนค่าที่อยู่ในตัวแปรแต่จะ return ค่าของตัวแปรที่ถูก shifted แล้วออกมา ถ้าคุณผู้อ่านยังมองไม่เห็นภาพก็ลองมายกตัวอย่างเล็ก ๆ กันดูดีกว่านะครับ

โปรแกรมที่ 3
1    // bitShiftTest.java
2    public class bitShiftTest {
3      public static void main(String args[]) {
4        byte a = 7;     // a is 00000111 in base 2
5        int b;
6        byte c;
7        b = a << 3;     // now b is 000...00111000 in base 2 or 56
8        System.out.println("int of 7 << 3 is equal to " + b);
9        b = a << 6;     // now b is 000...00111000000 in base 2 or 448
10       System.out.println("int of 7 << 6 is equal to " + b);
11       c = (byte)(a << 6);     // now c is 11000000 in base 2 or -64
12       System.out.println("byte of 7 << 6 is equal to " + c);
13     }
14   }

ในโปรแกรมข้างบนนี้เราใช้ left shift เป็นตัวอย่าง เนื่องจาก a เป็นตัวแปรแบบ byte ซึ่งมี 8 บิต ค่าของ a ซึ่งเท่ากับ 7 ในฐานสองก็คือ 000001112 ในบรรทัดที่ 3 นั้นค่าของ a ซึ่งถูก shifted ไป 3 บิตนั้นถูก returned มาอยู่ในรูปของ int (32 bit) ซึ่งเท่ากับ 56 ในบรรทัดที่ 9 นั้นค่าของ a ที่ถูก shifted ไป 6 บิตนั้นก็ถูก returned มาในรูปของ int (32 bit) ซึ่งเท่ากับ 448 แต่ในบรรทัดที่ 11 นั้นค่า return ได้ถูก casted เป็น byte เพราะฉะนั้นบิตที่สูงเกินกว่า 8 จึงถูกกำจัดไป

ค่า return ของ << และ >> นั้นจะเป็น int ถ้า operand นั้นเล็กกว่าหรือเท่ากับ int เพราะฉะนั้นในบรรทัดที่ 11 เราจึงต้อง cast ค่า return ให้เป็น byte แต่ถ้า operand นั้นเป็น long ล่ะก็ค่า return ก็จะเป็น long

7.2 &, ^ และ |
& หมายถึง and ในภาษาคอมพิวเตอร์ โอเปอเรเตอร์ & นั้นจะเปรียบเทียบทีละบิตในหลักเดียวกันของสอง operands ถ้าอย่างน้อยหนึ่งในสองบิตนั้นเป็นศูนย์ผลลัพธ์ของการ and ในบิตนั้นก็จะเป็นศูนย์ ถ้าทั้งสองบิตเป็นหนึ่งผลลัพธ์ของบิตนั้นก็จะเป็นหนึ่ง
| หมายถึง or ในภาษาคอมพิวเตอร์ โอเปอเรเตอร์ | นั้นจะเปรียบเทียบทีละบิตในหลักเดียวกันของสอง operands ถ้าอย่างน้อยหนึ่งในสองบิตนั้นเป็นหนึ่งผลลัพธ์ของการ or ในบิตนั้นก็จะเป็นหนึ่ง ถ้าทั้งสองบิตเป็นศูนย์ผลลัพธ์ของบิตนั้นก็จะเป็นศูนย์
^ หมายถึง exclusive or ในภาษาคอมพิวเตอร์ โอเปอเรเตอร์ ^ นั้นจะเปรียบเทียบทีละบิตในหลักเดียวกันของสอง operands ถ้าทั้งสองบิตนั้นค่าเหมือนกันผลลัพธ์ของการ exclusive or ในบิตนั้นก็จะเป็นศูนย์ ถ้าทั้งสองบิตค่าไม่เหมือนกันผลลัพธ์บิตนั้นก็จะเป็นหนึ่ง เราลองมาดูตัวอย่างข้างล่างกันดีกว่าครับ

โปรแกรมที่ 4
1    // logicalTest.java
2    public class logicalTest {
3      public static void main(String args[]) {
4        byte a = 51;        // a = 00110011 in base 2
5        byte b = -102;      // b = 10011010 in base 2
6        byte c;
7
8        c = (byte)(a & b);  // c = 18 or 00010010 in base 2
9        System.out.println("00110011 & 10011010 is equal to " + c);
10       c = (byte)(a ^ b);  // c = -87 or 10101001 in base 2
11       System.out.println("00110011 ^ 10011010 is equal to " + c);
12       c = (byte)(a | b);  // c = -69 or 10111011 in base 2
13       System.out.println("00110011 | 10011010 is equal to " + c);
14     }
15   }

ค่าของ a และ b ซึ่งเป็นตัวแปรแบบ byte คือ 001100112 และ 100110102 ตามลำดับ ถ้าเราเอา a มา and กับ b บิตที่ได้ค่าหนึ่งก็คิอบิตที่หนึ่งและสี่ (นับบิตทางขวาสุดเป็นบิตที่ศูนย์ และตัวถัดมาทางซ้ายเป็นบิตที่หนึ่ง) ถ้าเราเอา a มา exclusive or กับ b บิตที่ได้ค่าหนึ่งก็คิอบิตที่ศูนย์ สาม ห้า และเจ็ด ถ้าเราเอา a มา or กับ b บิตที่ได้ค่าหนึ่งก็คิอบิตที่ศูนย์ หนึ่ง สาม สี่ ห้า และเจ็ด

5.3 ~(one's complement)
~ เป็นบิตโอเปอเรเตอร์อันเดียวที่เป็น unary โอเปอเรเตอร์ ถ้า operand เป็นตัวแปรที่เล็กกว่า int มันจะถูก casted ให้เป็น int ก่อนแล้วจึงถูกทำ one's complement (คุณผู้อ่านที่สงสัยเกี่ยวกับ one's complement และ casting กรุณากลับไปอ่านที่บทความเรื่อง Primitive Datatype นะครับ) แล้วจึงถูก returned ออกมา โปรดสังเกตว่าค่าของ operand จะไม่ถูกเปลี่ยน เนื่องจาก one's complement = two's complement - 1 และจาวาคอมไพเลอร์ใช้ two's complement แทนค่าลบ เราจึงสรุปได้ว่า ~a จะเท่ากับ (-a-1) เสมอ

โปรแกรมที่ 5
1    // complementTest.java
2    public class complementTest {
3      public static void main(String args[]) {
4        byte a = 14;        // a = 00001110 in base 2
5
6        int b = ~a;         // now b is a complement of (int)a
7                            // which is 111...10001 base 2 or -15 base 10
8        byte c = (byte)~a;  // ~a is casted to byte before assigned to c
9                            // c is equal to 11110001 base 2 or -15 base 10
9        System.out.println("int a = 14");
10       System.out.println("int b = ~a = " + b);
11       System.out.println("byte c = (byte)~a = " + c);
12     }
13   }

6. โอเปอเรเตอร์ในการตั้งค่า
โอเปอเรเตอร์ในการตั้งค่านั้นทั้งหมดเป็นแบบ binary โอเปอเรเตอร์เนื่องจากต้องมีการเอาค่าไปใส่ในตัวแปรจึงต้องมีสอง operands เสมอ

ตารางที่ 5 โอเปอเรเตอร์ในการตั้งต่า

โอเปอเรเตอร์ในการตั้งค่า
=
*=
/=
%=
+=
-=
<<=
>>=
&=
^=
|=

โอเปอเรเตอร์ที่คุณผู้อ่านเห็นในตารางก็คือโอเปอเรเตอร์ที่คุณผู้อ่านได้รู้จักมาแล้วนั่นแหละครับเพียงแต่เติมเครื่องหมายเท่ากับเข้าไปเท่านั้นเอง โอเปอเรเตอร์พื้นฐานที่สำคัญที่คุณผู้อ่านได้เจอมาแล้วในแทบทุกตัวอย่างก็คือ "=" เจ้าโอเปอเรเตอร์เท่ากับนี้ทำหน้าที่สองอย่าง อย่างแรกคือเอาค่าที่อยู่ทางซ้ายมาใส่ไว้ในตัวแปรที่อยู่ทางขวา เพราะฉะนั้นทางขวาของโอเปอเรเตอร์นี้จะเป็นตัวแปรหรือเป็นค่า Literal Constant ก็ได้แต่ทางด้านซ้ายของโอเปอเรเตอร์จะต้องเป็นตัวแปรเท่านั้นและจะต้องเป็นชนิดเดียวกันกับตัวแปรหรือค่าที่อยู่ทางขวาด้วย ลองมาดูตัวอย่างเล็ก ๆ ข้างล่างดีกว่าครับ

โปรแกรมที่ 6
1    // assignTest1.java
2    public class assignTest1 {
3      public static void main(String args[]) {
4        int a;
5        a = 20;       // OK
6        20 = a;       // Not OK: Assign variable to literal constant
7        a = 2.789;    // Not OK: Assign double literal to int variable
8        a = (int)2.789;   // OK with casting
9      }
10   }

ในบรรทัดที่ 6 นั้นจะไม่สามารถคอมไพล์ผ่านได้เนื่องจากทางด้านซ้ายของเครื่องหมายเท่ากับนั้นไม่ใช่ตัวแปร ส่วนบรรทัดที่ 7 นั้นค่าที่อยู่ทางซ้ายของเครื่องหมายเท่ากับเป็นแบบ double เพราะฉะนั้นจึงต้อง cast ให้เป็น int เสียก่อนจึงจะใส่เข้าไปในตัวแปร a ได้

หน้าที่อย่างที่สองของโอเปอเรเตอร์เท่ากับคือ return ค่าที่เพิ่งใส่เข้าไปในตัวแปรที่อยู่ทางซ้าย เรามาดูตัวอย่างเล็ก ๆ กันอีกอันนะครับ

โปรแกรมที่ 7
1    // assignTest2.java
2    public class assignTest2 {
3      public static void main(String args[]) {
4        int a, b, c;
5
6        a = 10; b = 20; c = 30;
7        a = b = c;
8        System.out.println("After a = b = c");
9        System.out.println("a="+a+" b="+b+" c="+c);
10
11       a = 10; b = 20; c = 30;
12       c = b = a;
13       System.out.println("After c = b = a");
14       System.out.println("a="+a+" b="+b+" c="+c);
15     }
16   }

ในบรรทัดที่ 7 นั้น b = c ถูก evaluated ก่อนเพราะฉะนั้นค่า b จึงเท่ากับ 30 หลังจากนั้นโอเปอเรเตอร์เท่ากับจึงรีเทอร์นค่า 30 ออกมาเพื่อไปเป็นค่าทางขวาของโอเปอเรเตอร์เท่ากับตัวถัดไป หลังจากโอเปอเรเตอร์เท่ากับตัวที่สองถูก evaluated ค่าของ a จึงเท่ากับ 30 เพราะฉะนั้นคุณผู้อ่านจึงบอกได้เลยว่าถ้ามีโอเปอเรเตอร์เท่ากับหลายๆตัวอยู่ในบรรทัดเดียวกันค่าของตัวแปรทั้งหมดก็จะเท่ากันและเท่ากับค่าที่อยู่ทางขวาสุด

ส่วนโอเปอเรเตอร์ในการตั้งค่าอื่น ๆ นั้นคุณผู้อ่านคงจะดูคุ้น ๆ ใช่ใหมครับ หน้าที่ทุกอย่างเกือบจะเหมือนกับโอเปอเรเตอร์ธรรมดาที่ไม่มีเครื่องหมายเท่ากับแต่เพิ่มเติมเข้ามาว่าตัวแปรที่อยู่ทางซ้ายของโอเปอเรเตอร์จะถูก assigned ค่าด้วยค่ารีเทอร์นของโอเปอเรเตอร์ คุณผู้อ่านลองดูตัวอย่างข้างล่างประกอบด้วยนะครับ

โปรแกรมที่ 8
// assignTest3.java
public class assignTest3 {
  public static void main(String args[]) {
    int a = 20;
    System.out.println("a = " + a);
    a += 10;     // now a = 30
    System.out.println("After a += 10: a = " + a);
    a -= 5;      // now a = 25
    System.out.println("After a -= 5: a = " + a);
  }
}

8. โอเปอเรเตอร์ลอจิกหรือโอเปอเรเตอร์ทางตรรกศาสตร์
โอเปอเรเตอร์ทางตรรกศาสตร์ประกอบไปด้วย "และ" (and), exclusive or, "หรือ" (or) และ "นิเสธ"(not)

ตารางที่ 6 โอเปอเรเตอร์ลอจิก

โอเปอเรเตอร์ลอจิก
หน้าที่
a & b
ถ้า a และ b เป็น true ทั้งคู่ โอเปอเรเตอร์ & จะรีเทอร์นค่า true, ถ้ามีค่าใดค่าหนึ่งเป็น false โอเปอเรเตอร์จะรีเทอร์นค่า false
a ^ b
ถ้า a และ b เป็นค่าเหมือนกันไม่ว่าจะเป็น true หรือ flase โอเปอเรเตอร์ ^ จะรีเทอร์นค่า false, ถ้าต่างกันโอเปอเรเตอร์จะรีเทอร์นค่า true
a | b
ถ้า a และ b เป็น flase ทั้งคู่ โอเปอเรเตอร์ | จะรีเทอร์นค่า false, ถ้ามีค่าใดค่าหนึ่งเป็น true โอเปอเรเตอร์จะรีเทอร์นค่า true
!a
ถ้าค่า a เป็น true โอเปอเรเตอร์จะรีเทอร์นค่า false, ถ้าค่า a เป็น false โอเปอเรเตอร์จะรีเทอร์นค่า true

คุณผู้อ่านได้เจอกับสัญลักษณ์ &, ^ และ | มาแล้วในข้อ 5 ซึ่งทำหน้าที่เป็นบิตโอเปอเรเตอร์ แต่ว่าโอเปอเรเตอร์ที่เรากำลังจะพูดต่อไปนี้ทำหน้าที่ต่างกันทั้ง ๆ ที่ใช้สัญลักษณ์เดียวกัน จาวาคอมไพเลอร์จะดูที่ตัว operands ของโอเปอเรเตอร์ ถ้าตัว operands เป็นตัวแปรแบบ byte, short, int หรือ long คอมไพเลอร์จะคิดว่าโอเปอเรเตอร์เป็นบิตโอเปอเรเตอร์ แต่ถ้า operands เป็นตัวแปรแบบ boolean (true or false) คอมไพเลอร์จะคิดว่าโอเปอเรเตอร์เป็นลอจิกโอเปอเรเตอร์ มีหลาย ๆ กรณีที่เราต้องใช้โอเปอเรเตอร์ & และ | ในบรรทัดเดียวกัน โอเปอเรเตอร์ & ถูก evaluated ก่อนโอเปอเรเตอร์ | หรือพูดอีกนัยหนึ่งก็คือโอเปอเรเตอร์ & มี precedence สูงกว่าโอเปอเรเตอร์ | อย่างไรก็ตามเราสามารถใช้เครื่องหมายวงเล็บเพื่อบังคับให้โอเปอเรเตอร์ที่เราต้องการถูก evaluated ก่อนได้ เราลองมาดูตัวอย่างกันดีกว่าครับ

โปรแกรมที่ 9
1    // logicOpTest.java
2    public class logicOpTest {
3      public static void main(String args[]) {
4        boolean T = true;
5        boolean F = false;
6
7        boolean result;
8
9        result = T & T;
10       System.out.println("true & true = " + result);
11       result = T & F;
12       System.out.println("true & false = " + result);
13       result = F & F;
14       System.out.println("false & false = " + result);
15       result = T ^ T;
16       System.out.println("true ^ true = " + result);
17       result = T ^ F;
18       System.out.println("true ^ false = " + result);
19       result = F ^ F;
20       System.out.println("false ^ false = " + result);
21       result = T | T;
22       System.out.println("true ^ true = " + result);
23       result = T | F;
24       System.out.println("true | false = " + result);
25       result = F | F;
26       System.out.println("true ^ false = " + result);
27       result = !T;
28       System.out.println("!true = " + result);
29       result = !F;
30       System.out.println("!false = " + result);
31       result = T | T & F | F;  // equivalent to T | (T & F) | F
32       System.out.println("true | true & false | false = " + result);
33       result = (T | T) & (F | F);  // now | is evaluated first
34       System.out.println("(true | true) & (false | false) = " + result);
35     }
36   }

9. โอเปอเรเตอร์คอนดิชันนัล
โอเปอเรเตอร์คอนดิชันนัลประกอบไปด้วย "&&", "||" และ "?:" คุณผู้อ่านคงจะเดาจากสัญลักษณ์ได้ว่าโอเปอเรเตอร์คอนดิชันนัลนั้นคงจะมีส่วนคล้ายกับโอเปอเรเตอร์ลอจิก โอเปอเรเตอร์คอนดิชันนัลนั้น operate บน operand แบบ boolean เหมือนกับโอเปอเรเตอร์ลอจิกแต่ต่างกันตรงที่โอเปอเรเตอร์คอนดิชันนัลนั้น evaluate ค่าเท่าที่จำเป็น คุณผู้อ่านอ่านมาถึงจุดนี้แล้วอาจจะสับสนเล็กน้อยนะครับว่าเท่าที่จะเป็นนันหมายความว่าอะไรกันแน่ ขอให้ลองอ่านต่อไปก่อนนะครับแล้วทุกอย่างจะค่อย ๆ กระจ่างขึ้น

9.1 โอเปอเรเตอร์ && และ ||
โอเปอเรเตอร์ลอจิก & นั้นจะ evaluate ทั้งค่าทางซ้ายและทางขวาของตัวเอง และถ้าทั้งคู่เป็น true โอเปอเรเตอร์ลอจิก & จะรีเทอร์นค่า true ส่วนโอเปอเรเตอร์คอนดิชันนัล && นั้นทำงานเหมือนกับโอเปอเรเตอร์ลอจิก & เกือบทุกอย่างยกเว้นแต่ว่าถ้าทางซ้ายของตัวเองเป็น false โอเปอเรเตอร์จะรีเทอร์นค่า false ทันทีโดยที่ไม่ evaluate ค่าทางขวา หมายความว่าโอเปอเรเตอร์ && จะไม่สนใจว่าค่าทางขวาของตัวมันเองเป็นอะไรเนื่องจากตามหลักลอจิก "and" นั้นถ้ามีตัวใดตัวหนึ่งเป็น false แล้วล่ะก็ทั้งหมดก็จะเป็น false ทันที

โอเปอเรเตอร์ลอจิก | นั้นจะ evaluate ทั้งค่าทางซ้ายและทางขวาของตัวเอง และถ้าทั้งคู่เป็น false โอเปอเรเตอร์ลอจิก | จะรีเทอร์นค่า false ส่วนโอเปอเรเตอร์คอนดิชันนัล || นั้นทำงานเหมือนกับโอเปอเรเตอร์ลอจิก | เกือบทุกอย่างยกเว้นแต่ว่าถ้าทางซ้ายของตัวเองเป็น true โอเปอเรเตอร์จะรีเทอร์นค่า true ทันทีโดยที่ไม่ evaluate ค่าทางขวา หมายความว่าโอเปอเรเตอร์ || จะไม่สนใจว่าค่าทางขวาของตัวมันเองเป็นอะไรเนื่องจากตามหลักลอจิก "or" นั้นถ้ามีตัวใดตัวหนึ่งเป็น true แล้วล่ะก็ทั้งหมดก็จะเป็น true ทันที

โอเปอเรเตอร์คอนดิชันนัล && และ || นั้นเปรียบเทียบได้กับอัลกอริทึมข้างล่างนี้

สำหรับ a && b
if(evaluate(a) == true) {
  return evaluate(b);
}
else {
  return false;
}

สำหรับ a || b
if(evaluate(a) == false) {
  return evaluate(b);
}
else {
  return true;
}

ทั้ง a และ b ในอัลกอริทึมข้างบนนั้นจะต้องเป็นค่าแบบ boolean (true or false), ตัวแปร แบบ boolean หรือ expression หรือ method ที่รีเทอร์นค่า boolean เท่านั้น (เราจะพูดถึง method ในบทความต่อ ๆ ไปนะครับ) คำว่า expression นั้นหมายถึงการรวมกันของ ตัวแปรหรือค่าและโอเปอเรเตอร์เข้าด้วยกันอย่างมีความหมาย ทีนี้คุณผู้อ่านคงจะเข้าใจมากขึ้นแล้วนะครับว่าการ evaluate ค่าเท่าที่จำเป็นนั้นหมายความว่าอย่างไร คุณสมบัตินี้จะทำให้การตัดสินใจของโปรแกรมเร็วขึ้นเล็กน้อยเนื่องจากว่าในบางกรณี expression ทางด้านขวาอาจจะไม่ถูก evaluated

9.2 โอเปอเรเตอร์ ?:
โอเปอเรเตอร์ ?: เป็นโอเปอเรเตอร์แบบ ternary ซึ่งต้องการ operands สามตัว มีลักษณะการใช้ดังนี้

expa ? expb : expc;

expa นั้นจะต้องเป็น expression ที่รีเทอร์นค่าแบบ boolean เท่านั้น ส่วน expb และ expc นั้นจะเป็น expression ที่รีเทอร์นค่าอะไรก็ได้ ในบรรทัดข้างบนนี้หมายความว่า "ถ้า expa นั้นรีเทอร์นค่า true ล่ะก็ expb จะถูก evaluated แต่ถ้ารีเทอร์นค่า false ล่ะก็ expc จะถูก evaluated แทน และโอเปอเรเตอร์ ?; ก็จะรีเทอร์นค่ารีเทอร์นของ expb หรือ expc ที่ถูก evaluated โอเปอเรเตอร์นี้ก็เปรียบเทียบได้กับ if-then-else อย่างย่อนั่นเอง

10. โอเปอเรเตอร์อื่นๆ
นอกเหนือจากโอเปอเรเตอร์ที่กล่าวมาทั้งหมดแล้ว ยังมีโอเปอเรเตอร์อื่น ๆ อีกที่คุณผู้อ่านควรจะรู้จักคือ instanceof, +, ., [ ], ( ) และ new โอเปอเรเตอร์

โอเปอเรเตอร์ instanceof นั้นมีลักษณะการใช้อย่างนี้

a instanceof b

โดยที่ a เป็นชื่อของ object และ b เป็นชื่อของ class (เรื่องของ object และ class เราจะมาคุยกันในบทความต่อ ๆ ไปนะครับ) โอเปอเรเตอร์ instanceof จะรีเทอร์นค่าแบบ boolean เป็น true ถ้า object a เป็น instance ของ class b หรือไม่ก็ subclass ของ b และจะรีเทอร์นค่า false ถ้า object a ไม่ใช่ instance ของ class b หรือ subclass ของ b

โอเปอเรเตอร์ + นอกจากจะเป็นโอเปอเรเตอร์ทางเรขาคณิตแล้วยังใช้เป็นโอเปอเรเตอร์ที่ใช้รีเทอร์น String object ที่เป็นการเชื่อมกันระหว่างสอง Strings objects ได้ ลักษณะการใช้ก็คือ

stringa + stringb

โอเปอเรเตอร์ + จะรีเทอร์น String object ที่มีค่าของ stringa ต่อด้วย stingb โดยที่มี stringa อยู่ทางซ้าย

โอเปอเรเตอร์ . ใช้สำหรับการอ้างถึงตัวแปร หรือ method ในแต่ละ object หรือ class ลักษณะการใช้ก็คือ

object_or_class_a.member_a
object_or_class_a.method_a()

โดยที่ object_or_class_a เป็น object หรือ class ก็ได้ และ member_a และ method_a เป็น variable หรือ method ใน object หรือ class นั้นตามลำดับ

โอเปอเรเตอร์ [ ] นั้นใช้อ้างถึงตัวแปรแต่ละตัวที่อยู่ใน array นะครับ เราจะกล่าวถึงในรายละเอียดในเรื่องของ array ในบทความต่อ ๆ ไป

โอเปอเรเตอร์ ( ) นั้นใช้เป็นตัวบ่งบอกถึง method เราจะกล่าวถึงในรายละเอียดในเรื่องของ method ในบทความต่อ ๆ ไป

โอเปอเรเตอร์ new นั้นเป็นโอเปอเรเตอร์ที่ใช้สำหรับสร้าง object ขึ้นมา เราจะกล่าวถึงในรายละเอียดในเรื่องของ class และ object ในบทความต่อ ๆ ไป

11. สิ่งที่คุณผู้อ่านควรจะได้รับหลังจากอ่านบทความนี้
11.1 รู้จักและสามารถใช้โอเปอเรเตอร์ต่าง ๆ ได้อย่างถูกต้อง
11.2 รู้จัก operand และค่ารีเทอร์นของแต่ละโอเปอเรเตอร์


Copyright (C) 2000 www.jarticles.com.