บทท่ี 4: Array และ String
โปรแกรมของเราเปรยี บเทียบ first กับ second ดวยการตรวจสอบคาทีไ่ ดจ ากการเปรยี บเทียบกบั 0 intro. to Java (FEU.faa)
ซงึ่ ถา first มากกวา second ประโยคน้ีก็จะเปน true แตเนอ่ื งจากวา first น้นั ไมมากกวา second
การเปรียบเทยี บของเราจึงใหผลลัพธเปน false Java จึงประมวลผลประโยคทอ่ี ยใู น else (สงผลลพั ธ
ไปหนาจอ) – การประมวลผลประโยคอนื่ ๆ ก็คลายกนั
โดยท่วั ไปเราจะเปรยี บเทยี บคาทไี่ ดจ าก method compareTo() กับ 0 เสมอเพราะจะทําใหเราไดค า
true หรอื false ทส่ี ามารถนําไปใชในการเลือกประมวลผลประโยคตาง ๆ ไดตามทเี่ ราตอ งการ
การเปรียบเทยี บความเหมอื นและเทา กันก็ทําไดด วยการใชเครอ่ื งหมาย == ดังเชนประโยคสุดทาย
ของโปรแกรม
if(str1.compareTo(str2) == 0)
out.println(str1 + " equals " + str2);
ในการเปรยี บเทยี บดว ย method compareTo() นคี้ า ทส่ี งกลบั มาเปน ไปไดเ พียงแค 3 คา คือ
-1, 0, และ 1 เทา นน้ั โดยท่ี
-1 หมายถงึ string ทอ่ี ยทู างซา ย นอ ยกวา string ทอ่ี ยูทางขวา (string ทีเ่ ปน parameter)
0 หมายถึง string ทั้งสองน้ันเทากัน
1 หมายถงึ string ทอี่ ยทู างซา ย มากกวา string ทอี่ ยูทางขวา
เชน ถาเรามปี ระโยค string1.compareTo(string2);
string1 หมายถงึ string ท่ีอยูทางซาย
string2 หมายถึง string ทอ่ี ยทู างขวา หรอื string ท่เี ปน parameter
4.8.5 การเขาหาตวั อักษรที่อยูใ น string
เราสามารถทจี่ ะเขา หาตวั อกั ษรตา ง ๆ ท่ีอยูใน string ไดดว ยการใช method ตา ง ๆ ดังทีไ่ ดแ สดงไว
เปน ตัวอยา งในโปรแกรม StringChars.java
1: /**
2: Counting number of vows, lowercase letters,
3: uppercase letters, consonants, and white spaces
4: */
5:
6: import static java.lang.System.out;
7: import java.lang.Character;
8:
9: class StringChars {
10: public static void main(String[] args) {
11: //setting up constant string
12: String string = "Learn to write programs in Java" +
13: " doesn't take as long as I think" +
14: " it would. But to fully understand" +
15: " it is a time consuming task.";
16:
17: int charCount = 0; //count of letters
18: int vowelCount = 0; //count of vowels
19: int lowerCaseCount = 0; //count of lowercase letters
20: int upperCaseCount = 0; //count of uppercase letters
21: int spaceCount = 0; //count of white spaces
22:
23: //check all letters
24: for(int i = 0; i < string.length(); i++) {
25: char ch = string.charAt(i);
26:
27: //check if it's a letter
28: if(Character.isLetter(ch))
29: charCount++;
30:
31: //check if it's an uppercase
32: if(Character.isUpperCase(ch))
33: upperCaseCount++;
34:
35: //check if it's a lowercase
147
เริ่มตนการเขยี นโปรแกรมดวย Java
36: if(Character.isLowerCase(ch)) intro. to Java (FEU.faa)
37: lowerCaseCount++;
38:
39: //check if it's a white space
40: if(Character.isWhitespace(ch))
41: spaceCount++;
42:
43: //convert it to lowercase
44: ch = Character.toLowerCase(ch);
45:
46: //check if it's a vowel
47: if(ch == 'a' || ch == 'e' ||
48: ch == 'i' || ch == 'o' || ch == 'u')
49: vowelCount++;
50: }
51:
52: out.println(charCount + " characters counted.");
53: out.println(upperCaseCount + " uppercase letters counted.");
54: out.println(lowerCaseCount + " lowercase letters counted.");
55: out.println(vowelCount + " vowels counted.");
56: out.println(charCount - vowelCount + " consonants counted.");
57: out.println(spaceCount + " spaces counted.");
58: }
59: }
ผลลัพธที่ไดจากการ run คอื
99 characters counted.
4 uppercase letters counted.
95 lowercase letters counted.
37 vowels counted.
62 consonants counted.
24 spaces counted.
การทํางานของโปรแกรมเรมิ่ ตนดว ยการกําหนดใหต ัวแปร string มีคา เปนคา คงทที่ ี่อยูใน " " เราจะ
เขา หาตวั อักษรแตล ะตัวดว ย for/loop และดงึ เอาตัวอักษรออกมาจาก string แตละตัวดว ยคาํ ส่งั
char ch = string.charAt(i)
ซ่ึงจะดึงเอาตัวอักษร ณ ตําแหนง index i นน้ั ๆ มาเก็บไวท ่ีตัวแปร ch หลังจากนนั้ ก็ตรวจสอบดว ย
method ตาง ๆ ท่มี ีอยใู น class Character เชน
Character.isLetter(ch) ใหคา true ถาเปน ตวั อักษร
Character.isUpperCase(ch) ใหค า true ถาเปน ตวั อักษรตวั ใหญ
Character.isLowerCase(ch) ใหคา true ถาเปน ตวั อักษรตัวเลก็
Character.isWhitespace(ch) ใหคา true ถาเปน ชองวาง (เคาะแปน หรอื tab)
พรอ มทั้งเพิ่มคาใหก ับตวั แปรทงั้ หลายทเ่ี ปนทเ่ี กบ็ จาํ นวนคร้ังของตัวอกั ษรตาง ๆ ทป่ี รากฏใน string
หลงั จากนั้นก็เปลีย่ นตวั อักษรใหเปน ตวั เล็กเพือ่ ใชต รวจสอบวาเปน สระในภาษาอังกฤษหรอื ไม สาเหตุ
ที่เปลี่ยนเพราะเราไมอยากท่จี ะเสียเวลาในการตรวจสอบสระตวั เล็กทีหนึ่ง และตวั ใหญอกี ทีหนึง่
อยางไรก็ตามท้ังสองก็เปน สระอยูเสมอ
ch = Character.toLowerCase(ch);
if(ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
vowelCount++;
ยังมี method อกี มากมายใน class Character และ class String ทเี่ ราสามารถนํามาใชในการทํางาน
ทเี่ ก่ยี วขอ งกบั string ตวั อยา งตอ ไปน้ีเปนการคน หาคํา (sub string) ท่อี ยใู น string ดว ยการใช
method indexOf()
1: /**
2: Using index to get to character in array
3: */
4:
5: import static java.lang.System.out;
6: import java.lang.Character;
7:
148
บทที่ 4: Array และ String intro. to Java (FEU.faa)
8: class IndexOf {
9: public static void main(String[] args) {
10: //setting up constant string
11: String string = "Learn to write programs in Java" +
12: " doesn't take as long as I think" +
13: " it would. But to fully understand" +
14: " it is a time consuming task.";
15:
16: int itCount = 0; //count of it
17: String it = "it"; //string to seach for
18:
19: //search for "it"
20: int index = string.indexOf(it);
21: while(index >= 0) {
22: itCount++;
23: //move to first letter after last "it"
24: index += it.length();
25: //look for next "it"
26: index = string.indexOf(it, index);
27: }
28:
29: out.println("The word 'it' appeared " +
itCount + " times.");
30: }
31: }
ผลลัพธข องโปรแกรมคือ
The word 'it' appeared 3 times.
โปรแกรมของเรากําหนดให index มคี า เปนตาํ แหนงท่ี "it" ปรากฏอยูใน string ดวยคาํ ส่งั
int index = string.indexOf(it)
เมื่อการคน หาประสพผลสําเรจ็ เราก็จะใช while/loop ในการคน หาตอ ไป แตก อ นท่ีเราจะดําเนินการ
น้นั เราจะเพมิ่ คาหนงึ่ คาใหก บั itCount กอน หลงั จากน้นั เราจะเล่ือน index ไปอยูในตําแหนง ของ
ตวั อกั ษรตัวแรกท่อี ยหู ลัง "it" ดว ยคําสั่ง index += it.length() เนื่องจากวา method indexOf() จะ
สง คา ของตําแหนงของตวั อกั ษรตัวแรกของ "it" มาให เสร็จแลวกท็ าํ การคน หาตอไปดวยคําสง่ั
index = string.indexOf(it, index)
ทําการคน หาไปจนกระทงั่ หมด string เราก็ออกจาก while/loop
ในการใช indexOf() คนหานน้ั เราตอ งเปรยี บเทยี บคาท่สี ง กลบั มากับ 0 เพราะถาหาไมเ จอคา ของ
index กจ็ ะเปน -1 ทาํ ใหเราหลุดออกจาก while – loop ได
Method indexOf() นัน้ มอี ยูสองตัวทีร่ บั เงอื่ นไข (parameter) ไมเหมอื นกัน ดงั ท่เี หน็ ในโปรแกรม
ตัวแรกรบั เพยี งคาเดยี วคอื sub string ทีต่ องการคน หา สวนตัวทส่ี องรบั คา สองคา คอื sub string ท่ี
ตองการคนหา และ จดุ (index) เริ่มตน ของการคนหา ซงึ่ ถาสงั เกตใหด เี ราใช indexOf() ตวั แรกใน
การคน หาคร้งั แรก และตวั ทีส่ องในการคนหาตวั ตอ ๆ ไป ทัง้ น้กี ็เพราะวาครั้งแรกสุดเราไมรวู า คาของ
index แตใ นครั้งที่สองนั้นเราไดคา ของ index แลว
ผูอา นตอ งจาํ ไวเสมอวา indexOf() จะสง คา -1 มาใหถา ไมม ี sub string ใน string นนั้ ๆและจะสงคา
ของตาํ แหนงท่ี sub string น้นั อยูถ ามี sub string ที่วา
ตอ ไปเราลองมาดูโปรแกรมทีท่ ําการดงึ เอากลมุ ของตวั อักษร (คาํ ) หรือทเี่ รียกวา sub string ออก
จาก string ดู
1: /**
2: Get to certain words in string
3: */
4:
5: import java.lang.Character;
6:
7: class SubString {
149
เริม่ ตนการเขยี นโปรแกรมดวย Java
8: public static void main(String[] args) { intro. to Java (FEU.faa)
//setting up constant string
9: String string = "Learning Java";
10:
String str1 = string.substring(0); //the whole string
11: String str2 = string.substring(9); //string: "Java"
12: String str3 = string.substring(0, 8);//string: "Learning"
13:
System.out.println("str1 > " + str1);
14: System.out.println("str2 > " + str2);
15: System.out.println("str3 > " + str3);
16: }
17:
18:
19:
20: }
Java มี method substring() ใหเราใชอ ยูสองตัว คือ substring() ที่ไมมี parameter และ
substring() ที่มี parameter อยูสองตัว โดยที่ตัวแรกเปน index เร่มิ ตนของ sub string และ
parameter ตวั ที่สองเปน index ตวั สุดทายท่อี ยใู น sub string นัน้ แตไมน ับตัวมนั เอง ดงั ท่ีไดแ สดง
ไวใ นโปรแกรม
String str2 = string.substring(9)
หมายความถงึ การเรมิ่ นับที่ index = 9 ไปจนถึงตวั สุดทา ยใน string นนั้ คือ เรมิ่ ทต่ี ัวอกั ษร 'J' ไปจบ
ทีต่ ัวอกั ษร 'a' ซึง่ คือคาํ วา "Java" สว น
String str3 = string.substring(0, 8)
หมายถึงการเร่ิมนบั ท่ี index = 0 ไปจนถงึ ตัวท่ี 8 คือตั้งแตต วั อักษร 'L' ไปจนถึงตวั อกั ษร ' ' (space)
แตไ มนับ space ดงั น้นั sub string ท่ีเราไดก ็คอื "Learning"
เราสามารถทจี่ ะดงึ เอา sub string ออกจาก string ทเ่ี ปนคาคงทีไ่ ด เชน
String sub = "Basic idea about Java".substring(6) จะให "idea about Java"
หรือ
String sub = "Basic idea about Java".substring(6, 10) จะให "idea"
ตารางท่ี 4.1 แสดงถึง method บางสว นของ class String
ตาราง 4.1 method บางสวนของ class String
method ความหมาย
length() ความยาวของ String (จํานวนตัวอักษร)
indexOf(String) ตาํ แหนงเริ่มตนที่ String ตวั น้อี ยู ถา ไมม ีจะเปน -1
indexof(String, start index) ตําแหนง เร่ิมตน ท่ี String ตวั นี้อยูตามจุดทกี่ าํ หนด ถา
ไมม ีจะเปน -1
lastIndexof(String) ตําแหนงสดุ ทายของ String ตัวนี้ เทา กบั -1 ถาไมมี
lastIndexof(String, start index) ตําแหนงสดุ ทายของ String ตวั น้ีตามจุดท่กี ําหนด
เทา กบั -1 ถา ไมม ี
trim() String ทีไ่ มมี space อยูทัง้ ดานหนา และหลัง
substring(start index) คา ของ String ณ ตาํ แหนง ทกี่ าํ หนดจนจบ
substring(start index, end index) คา ของ String ณ ตําแหนงท่กี าํ หนดท้ังสอง
replace(old char, new char) เปลย่ี น char ทุกตัวดว ย char ตัวใหมทก่ี ําหนด
charAt(index) คาตวั อักษร ณ ตาํ แหนงทกี่ าํ หนด
equals(String) true ถา String ทงั้ สองตัวเทา กนั
equalsIgnoreCase(String) true ถา String ทัง้ สองตวั เทากนั ไมสนใจ case
startsWith(String) true ถา String เรม่ิ ตนดว ย String ทก่ี าํ หนด
startsWith(String, start index) true ถา String เริ่มตน ดวย String ทก่ี ําหนด ณ
ตาํ แหนงท่กี ําหนด
endsWith(String) true ถา String จบดวย String ทกี่ ําหนด
150
บทที่ 4: Array และ String intro. to Java (FEU.faa)
4.8.6 การใช class StringBuffer ในการสราง string
แทนท่จี ะใช class String เรากส็ ามารถท่ีจะใช class StringBuffer แทนได การทํางานกไ็ มแตกตาง
กันมากมายนัก เชน สมมติวา เราจะสราง string สักตวั หนึ่งเราก็ทําได ดังนี้
StringBuffer string = new StringBuffer("Basic String Operations");
เราสราง object หน่งึ ตวั ช่ือ string จาก class StringBuffer โดยกําหนดคาเบอ้ื งตนเปน "Basic
String Operations" เราไมส ามารถทจ่ี ะสราง string เหมือนกับทเ่ี ราสรา งดว ย class String ได เรา
ตองจองเนื้อท่ีใหกบั ตัวแปรดว ยคําสัง่ new กอน หลงั จากนัน้ กก็ ําหนดคา ใหกบั ตวั แปรนี้ เราอาจ
ประกาศดว ยการประกาศแบบน้ี
StringBuffer string = null;
string = new StringBuffer("Just another way to declare");
แตไมใชแบบน้ี
StringBuffer string = "Just another way to declare";
ขอ ดีของการใช StringBuffer กค็ ือ เราสามารถที่จะเปล่ียนแปลง string ทเ่ี ราสรางข้นึ ได (object
จาก class String ทเ่ี ราใชกอนหนา น้ีทาํ ไมไ ด) และเรายังสามารถที่จะกําหนดขนาดของ string จาก
class StringBuffer ไดตามความพึงพอใจของเรา ลองมาดูโปรแกรมตวั อยางการใช object จาก
class StringBuffer กนั
1: /**
2: Using StringBuffer
3: */
4:
5: class StringBufferTest {
6: public static void main(String[] args) {
7: //setting up constant string
8: StringBuffer string = new StringBuffer("fish");
9:
10: System.out.println("string is " + string);
11:
12: //append "er" after "fish"
13: string.append("er");
14: System.out.println("string is " + string);
15:
16: //append "man" after "fisher" using method insert()
17: string.insert(string.length(), "man");
18: System.out.println("string is " + string);
19:
20: string.setLength(6);
21: System.out.println("string after set length is " + string);
22:
23: //create new string and delete some characters
24: StringBuffer str = new StringBuffer("Java Programming");
25: System.out.println("string is " + str);
26: str.delete(4, str.length());
27: System.out.println("str after deleted " + str);
28: }
29: }
โปรแกรม StringBufferTest.java แสดงการสรา ง object จาก class StringBuffer ดวยคาํ สัง่
StringBuffer string = new StringBuffer("fish")
จะทาํ ใหคาของ string เปน
fish
uiui
หลงั จากทเ่ี ราแสดงขอมูลท่อี ยูใ น string แลวเราก็นาํ เอา string "er" มาเชอ่ื มเขากับ string "fish"
ดว ยคําส่งั
151
เริ่มตน การเขียนโปรแกรมดว ย Java intro. to Java (FEU.faa)
string.append("er")
จะทําใหค า ของ string เปน
fisher
ทําใหขอ ความที่อยใู น string เปลี่ยนเปน "fisher" และหลังจากทเี่ ราแสดงผลทไี่ ดใหมน ี้ไปยงั
หนาจอ เราก็เปลย่ี นขอ มลู ใน string ใหมดว ยการนําเอา string "man" มาเชื่อมเขากบั string ทเ่ี รา
ไดกอ นหนา นีด้ ว ยการใช method insert() ดงั น้ี
string.insert(string.length(), "man")
จะทําใหคา ของ string เปน
fisherman
เราเรยี ก insert() ดวย parameter 2 ตวั คือ 1). ความยาวของ string เดมิ ซงึ่ กค็ อื จดุ เริ่มตนของการ
เช่ือม และ 2). string ตวั ใหมทเี่ ราตอ งการเชื่อม คือ "man" เมอ่ื run ดูแลวผลลัพธทไ่ี ดค อื
string is fish
string is fisher
string is fisherman
เราสามารถท่ีจะเปลีย่ นขนาดของ object ที่มาจาก class StringBuffer ไดด ังน้ี
string.setLength(6)
ซึ่งจะทําใหขอ มลู ท่อี ยใู น string เปล่ยี นไป หลงั จากทเี่ ราเปลี่ยนขนาดของ string และเพ่มิ ประโยค
สําหรบั การแสดงผลในโปรแกรมของเราใหเ ปน
System.out.println("string after set length is " + string)
ผลลัพธท เี่ ราจะไดจ ากการ run กจ็ ะกลายเปน
string after set length is fisher
ในสวนของการลบขอความบางสว นดงั ท่ปี รากฏในบรรทัดท่ี 26 น้นั เราใชคาํ ส่ัง
str.delete(4, str.length());
ซงึ่ จะทําการลบตวั อกั ษรต้ังแตต ัวท่อี ยู ณ index = 4 ไปจนถึงตวั อกั ษรที่อยู ณ index ตัวสดุ ทา ยของ
str ซง่ึ ก็คือ index = 14
เราไมไ ดถูกจาํ กดั ใหใ สขอ มูลทีเ่ ปน string เทา น้นั ใน object ทมี่ าจาก class StringBuffer เรา
สามารถทีจ่ ะเรียกใช append() หรอื insert() กบั ขอมลู ชนิดอืน่ ๆ ได เชน โปรแกรมตัวอยางตอ ไปนี้
1: /**
2: Using StringBuffer
3: */
4:
5: import static java.lang.System.out;
6:
7: class StringBufferTest1 {
8: public static void main(String[] args) {
9: //setting up constant string
10: StringBuffer string = new StringBuffer();
11: string.append(2);
12: out.println("string is " + string);
152
บทท่ี 4: Array และ String intro. to Java (FEU.faa)
13:
14: //append " fisher" after 2
15: string.append(" fisher");
16: out.println("string is " + string);
17:
18: //append "men" after "fisher" using method insert()
19: string.insert(string.length(), "men");
20: out.println("string is " + string);
21:
22: string.append(" with ");
23: out.println("string is " + string);
24:
25: string.append(100);
26: string.append(" fish.");
27: out.println("string is " + string);
28:
29: StringBuffer s = new StringBuffer("Chiang Mai");
30: out.println("Length of " + s + " is " + s.length());
31:
32: int capacity = s.capacity();
33: out.println("Capacity of " + s + " is " + capacity);
34: }
35: }
เราไมไ ดท ําอะไรมากมายนักเพยี งแตเ รยี กใช method append() ดว ยคาท่เี ปน int เชน
string.append(2) หรอื string.append(100) เปนตน Java ยงั ยอมใหเ ราเชื่อมขอมลู ทม่ี ีความ
หลากหลายของชนิดของขอมูลเขา สู object ทีม่ าจาก class StringBuffer ไดโ ดยไมจ าํ กัดจาํ นวน
ผลลัพธข องโปรแกรมหลังจากการปรับปรงุ คือ
string is 2
string is 2 fisher
string is 2 fishermen
string is 2 fishermen with
string is 2 fishermen with 100 fish.
สวนหนึ่งของ class StringBuffer ที่นาสนใจกค็ อื การกาํ หนดขนาดใหก ับ buffer ที่รองรับขอมูลใน
object ตา ง ๆ ทีเ่ กดิ จาก class น้ี นนั่ กค็ ือ Java จะกาํ หนดขนาดของ buffer ใหเทากบั ขอมูลทีม่ อี ยู
ใน buffer บวกกับอกี 16 ตัวอักษรเสมอ เชน ถาเราสราง object
StringBuffer name = new StringBuffer("Chiang Mai");
ซึ่งมีจาํ นวนตัวอกั ษรทัง้ หมด (นบั ชอ งวางดวย) เทา กับ 10 ตวั Java จะจองเนื้อทใ่ี หมีความจุเทากบั
26 ตวั เราสามารถตรวจสอบความจุของ buffer ดว ยการเรยี กใช method capacity() ได เชน ถาเรา
สรางประโยคตอไปน้ี
StringBuffer s = new StringBuffer("Chaing Mai");
out.println("Length of " + s + " is " + s.length());
out.println("Capacity of " + s + " is " + s.capacity());
หลังจากการประมวลผล เราจะไดผ ลลพั ธดังนี้
Length of Chiang Mai is 10
Capacity of Chiang Mai is 26
ตัวอยางตอ ไปนีค้ งเปนตวั อยา งสุดทายทเ่ี ราจะแสดงใหเหน็ ถงึ การใช method อีกตัวหนงึ่ ในการ
เปล่ยี นแปลงขอ มูลท่อี ยูใน string ใหอยใู นรูปแบบของการกลบั หวั กลบั หาง (reverse)
1: /**
2: Reverse a string
3: */
4:
5: import static java.lang.System.out;
6:
7: class ReverseString {
8: public static void main(String[] args) {
9: //setting up a constant string
10: StringBuffer string = new StringBuffer("I love Chiang Mai");
153
เร่มิ ตนการเขียนโปรแกรมดว ย Java
11: intro. to Java (FEU.faa)
12: //create another string
13: StringBuffer revStr = new StringBuffer(string);
14:
15: revStr.reverse(); //reverse it
16:
17: out.printf("Reverse of [%s] is [%s]%n", string, revStr);
18: }
19: }
ผลลัพธข องการ run คือ
Reverse of [I love Chiang Mai] is [iaM gnaihC evol I]
หลังจากทีส่ ราง string ดว ยคา "I love Chiang Mai" แลว เรากส็ รา ง object อกี ตวั หนึง่ โดยไมมกี าร
อางถึงคาใด ๆ ทั้งส้ินดว ยคําสงั่ StringBuffer revStr = new StringBuffer() หลงั จากนั้นเรากส็ ราง
string อกี หนึ่งตวั ทีม่ คี าเหมอื นกบั string หลังจากนัน้ เราก็ใชค าํ สั่ง revStr.reverse() เพ่อื ทําการ
reverse ขอ มลู ที่อยูใน revStr ท่เี หลอื อยูก็คือการสงผลลัพธข องการ reverse ไปยังหนาจอ
ยงั มี method อกี มากมายทเี่ ราสามารถนาํ มาใชในงานที่เกย่ี วของกบั string แตเ ราคงไมส ามารถพดู
ในที่นไ้ี ดห มด จงึ เพียงแตห วงั วาผูอานจะทําการคน ควาตอไปเพื่อความเขา ใจในเรื่องท่ีเกี่ยวของกับ
string ตอ ไป ตารางท่ี 4.2 แสดงถงึ method ตาง ๆ ของ class StringBuffer
ตาราง 4.2 method บางสวนของ class StringBuffer
method ความหมาย
capacity() ความจขุ อง StringBuffer ตัวนี้
length() ความยาวของ StringBuffer ตวั น้ี
setLength(new length) กําหนดความยาวของ StringBuffer ดว ยความยาว
ใหม
append(value) เชือ่ มคา เขาทางดา นหลงั ของ StringBuffer ตวั น้ี
insert(index, value) เพิม่ คาเขาสู StringBuffer ณ ตําแหนง ที่กาํ หนด
replace(start index, end index, String) เปลีย่ นคา ตามจุดท่กี าํ หนด ดว ย String
delete(start index, end index) ลบคาออกตามจุดท่ีกําหนด
deleteCharAt(index) ลบตัวอักษรตามจดุ ทกี่ ําหนด
setCharAt(index, character) เปลีย่ นตัวอกั ษร ณ ตําแหนงท่กี ําหนด
charAt(index) คา ตัวอักษร ณ ตาํ แหนงที่กาํ หนด
substring(index) คา substring ตามจุดเรมิ่ ตน ท่กี ําหนดจนจบString
substring(start index, end index) คา substring ตามจดุ ทกี่ ําหนดเทา น้นั
toString() object ทม่ี คี าของ String ท่อี ยูใน StringBuffer
reverse() สลับตวั อกั ษรทุกตวั ใน StringBuffer
4.8.7 การกาํ หนดใหขอ มลู ของ array เปน string (Array of Strings)
เนื่องจากวา string เปน object ดังนน้ั เราจึงสามารถที่จะเก็บ string ไวใน array ได การจัดเกบ็
string ไวใน array กไ็ มยงุ ยาก ก็คลาย ๆ กับทเี่ ราเก็บขอมลู ชนดิ อืน่ ไวใ น array น่ันเอง มาถึงตอนนี้
ถาเราลองมองยอนกลับไปดูการประกาศ method main() ของเรา เราจะเห็นการประกาศแบบนี้
public static void main(String[] args) { …
ภายในเครอื่ งหมาย () เราจะเหน็ การประกาศ String [] args ซงึ่ เปนการประกาศใหตัวแปร args เปน
ตัวแปรทีใ่ ชเ ก็บ array of strings ซง่ึ การประกาศนกี้ เ็ หมือนกับการประกาศ array โดยทัว่ ไปเพียงแต
เราเปลย่ี นใหการจัดเก็บขอ มลู มาเปน string เทา นัน้ เอง ลองมาดูโปรแกรมตวั อยา งการสราง array of
strings กันดู
1: /**
2: Array of strings
3: */
4:
5: import static java.lang.System.out;
6:
7: class ArrayOfStrings {
154
บทที่ 4: Array และ String
8: public static void main(String[] args) { intro. to Java (FEU.faa)
//declare array of 5 strings
9: String[] names = new String[5];
10:
//initialize array
11: names[0] = "Chiang Mai";
12: names[1] = "Toronto";
13: names[2] = "Spokane";
names[3] = "Phoenix";
14: names[4] = "Walla Walla";
15:
16: String word = names[4].substring(0, 5);
out.printf("First word from names[%d] is %s%n", 4, word);
17:
18: for(String str : names) {
out.println(str);
19:
20: }
21: }
22:
23:
24:
25:
26: }
เราไดป ระกาศให names เปน array of Strings ท่สี ามารถเก็บขอมูลไดส ูงสุด 5 ตัว ดว ยคาํ สง่ั
String[] names = new String[5];
หลังจากนนั้ เราก็ใสขอมลู ใหก ับตําแหนง ตาง ๆ ของ array names และเม่ือใสค รบแลว เราดงึ เอาคํา
แรกทีอ่ ยูใน names[2] มาแสดง เมอื่ เสร็จแลวเรากแ็ สดงขอ มูลทงั้ หมดไปยงั หนา จอ ดวยการใช
for/loop ผลลพั ธของการ run คือ
First word from names[4] is Walla
Chiang Mai
Toronto
Spokane
Phoenix
Walla Walla
โปรแกรมตวั อยางท่เี หน็ เปนโปรแกรมอยา งงาย ทีเ่ ขียนขนึ้ มาเพอื่ แสดงการใช array of Strings
กระบวนการตา ง ๆ ทสี่ ามารถทําไดกับ array โดยท่วั ไปก็สามารถทําไดกับ array of Strings ดังน้ัน
ผอู า นควรยอ นกลับไปดเู ร่อื งของ array ทเี่ ราไดพูดถึง และลองประยุกตใ ชกระบวนการตา งๆ กับ
array of Strings ดเู พื่อใหเ กิดความเขาใจมากย่งิ ขึ้น
สรปุ
ในบทนเ้ี ราไดพ ูดถงึ การเกบ็ ขอ มูลดวย array การใช String และ StringBuffer รวมไปถึงกระบวนการ
ตา ง ๆ ทีเ่ ราสามารถทาํ ไดก บั ตัวแปร หรือ object ตาง ๆ ท่เี กดิ จาก class String และ class
StringBuffer ผูอ า นควรทําความเขา ใจกบั method ตาง ๆ ที่เราไดพ ดู ถึงเพอื่ การนําไปใชอยางมี
ประสทิ ธิภาพ จุดหลัก ๆ ทีเ่ ราไดพ ูดถงึ คอื
9 การสรา ง array ในการเก็บขอมลู ชนิดเดยี วกนั หลายตวั ไวในตัวแปรตวั เดยี ว
9 การเขาหาขอมลู แตล ะตัวใน array ดว ยการใช index
9 ขนาดของ array สามารถดงึ ออกมาจากตวั แปรคงที่ length
9 Array สามารถที่จะเกบ็ ขอมลู ที่เปน array ได
9 เราสราง object ทเ่ี ปน string จาก class String พรอ มทัง้ กําหนดคา ทไี่ มส ามารถเปลยี่ นแปลง
ได
9 ขนาดของ string ตอ งดงึ ออกมาจาก method length()
9 String มี method หลาย ๆ ตวั ใหเราใชในการจัดการกับ string
9 เราสรา ง string ท่ีสามารถเปลีย่ นแปลงไดจ าก class StringBuffer
9 StringBuffer มี method หลายตวั ทเี่ ราเรยี กใชในการจดั การกับ string ตา ง ๆ
9 ขนาดของ string จาก class StringBuffer หาไดจ าก method length() และความจขุ อง object
ทม่ี าจาก StringBufer หาไดด ว ยการเรียกใช method capacity()
155
เร่มิ ตนการเขยี นโปรแกรมดว ย Java intro. to Java (FEU.faa)
แบบฝก หัด
1. จงเขยี นโปรแกรมที่รบั ขอมลู ทเี ปน int จาก keyboard จาํ นวน 10 ตัว เก็บไวใ น array พรอ มทัง้
หาคา สงู สดุ คา ตาํ่ สุด จํานวนของขอ มูลท่เี ปนเลขคี่ทง้ั หมด และจํานวนของขอมูลท่ีเปน เลขคู
ทงั้ หมด
2. จงเขยี นโปรแกรมทใี่ ช Math.random() ในการสรางขอมลู จํานวน 100 ตวั เกบ็ ไวใ น array ให
แสดงขอ มลู ทัง้ หมดไปยงั หนาจอโดยใหม ีจํานวนขอ มลู เปน 5 แถว ๆ ละ 20 ตัว
3. จงเขียนโปรแกรมที่สราง array 2 มติ ขิ นาด 3 x 3 จาํ นวน 2 ตวั ท่มี ีขอมลู เปน int ใหใ สข อ มลู ใน
array ดวยการใช Math.random() ท่กี ําหนดใหคาของขอมลู ที่สรางขน้ึ อยูร ะหวาง 1 – 9
หลังจากนน้ั ใหนําเอา array 2 ตวั นมี้ าบวกกนั (Matrix addition) เกบ็ ผลลัพธท ้งั หมดทไี่ ดไวใ น
array ตวั ที่สาม พรอมทัง้ แสดง array ทั้งสามตัวไปยงั หนา จอ
4. จงเขยี นโปรแกรมท่ีรับ object จาก class String จาํ นวนสามตัวจาก keyboard ใหต รวจสอบวา
string ตวั ไหนใหญที่สุด และ string ตวั ไหนเล็กท่สี ดุ แสดงผลลพั ธไ ปยังหนา จอ
5. จงเขยี นโปรแกรมท่ใี ช array เก็บ string จาํ นวน 10 ตัวทอ่ี ยใู นรปู แบบของ day/month/year
เชน 02/10/00 ใหโ ปรแกรมตรวจสอบขอมูลทอ่ี ยใู น string ทกุ ตัว เสร็จแลว ใหส งผลลพั ธ
ทงั้ หมดในรูปแบบของ 2 October 2000 ไปยังหนา จอ
6. จงเขยี นโปรแกรมทใี่ ช array ในการเกบ็ char จํานวน 10 ตวั ใหท าํ การ reverse ขอมูลทอี่ ยใู น
array น้ี ผลลพั ธท่ไี ดใหเ กบ็ ไวใน array ตัวเดมิ
7. จงเขียนโปรแกรมท่ีใช StringBuffer เก็บ string จํานวน 10 ตัว ใหนํา string ทงั้ หมดไปเก็บไว
ใน string ตวั ใหมโดยให string ท่มี จี าํ นวนของ char นอ ยอยูท างดา นหนา และ string ท่มี ี
จาํ นวนของ char มากอยูท างดา นหลัง (เรยี งจากนอ ยไปหามาก)
8. จงเขียนโปรแกรมที่ใช array ในการเกบ็ ชอ่ื ของลูกคาจํานวน 20 ช่อื ใหทาํ การคน หาชือ่ ของ
ลกู คาท่ีมตี วั อกั ษรขึน้ ตน ตามท่ี user เปนผูกําหนดจาก keyboard ใหแสดงชอื่ ทุกตัวที่มอี ักษร
ขึ้นตนดังกลาวออกทางหนา จอ
9. กําหนดให array1 และ array2 เปน array ทเี่ กบ็ int จํานวนเทากับ 10 ตวั โดยที่ ขอมูลของแต
ละ array ไดถ กู จดั เรยี งใหอ ยูในรูปของ มากไปหานอย จงเขยี นโปรแกรมท่นี าํ เอาขอ มลู ของ
array ท้งั สองตัวมารวมกนั โดยทยี่ ังรกั ษาคณุ สมบตั ขิ องการเรียงจากมากไปหานอ ย เก็บไวใน
array ตัวใหม แสดงผลลัพธข องท้ังสาม array ออกทางหนา จอ
10. จงเขียนโปรแกรมท่รี ับ String 1 ตวั ท่ีประกอบไปดวย ช่ือตน และนามสกุลท่ถี ูกแบงดว ยชอ งวาง
(space) เชน Micha Sapporo หลงั จากนั้นใหแบง String ตวั นอี้ อกเปน 2 ตัวใหเปน ช่ือตน 1
ตัว และนามสกุล 1 ตัว
11. จงปรบั ปรงุ โปรแกรมในขอ 10 ใหทาํ หนา ทล่ี บชอ งวา งทอี่ าจนาํ หนา และตามหลงั ชื่อที่นาํ เขา
จาก keyboard
12. จงเขยี นโปรแกรมทรี่ ับ String 2 ตวั จาก keyboard ใหทาํ การคนหาวา String ตวั ที่สองมีอยูใ น
String ตวั แรกหรอื ไม ถา มี มีอยูกตี่ ัว อยทู ่ตี าํ แหนงใดบา ง
13. จงเขยี นโปรแกรมท่ีรบั String 2 ตวั จาก keyboard ใหน าํ เอา String ตัวทีส่ องไปใสไวใน
ตําแหนงทถ่ี กู กําหนดจาก user ถาตําแหนง ที่ user กําหนดเปน ไปไมไ ดใ หน ํา String นน้ั ไปใส
ไวดานหลงั ของ String ตัวแรก
156
บทที่ 4: Array และ String
14. จงเขยี นโปรแกรมทีท่ ําหนาที่ดังนี้
รับ String ในรูปแบบของ 112 Newell Street, Walla Walla, WA 99210 intro. to Java (FEU.faa)
ทําการตดั String ใหอยูใ นรปู แบบของ
No. 112
Street: Newell Street
City: Walla Walla
State: WA
Zip: 99210
15. จงเขียนโปรแกรมทที่ าํ การสลับคําทมี่ อี ยใู น String เชน ถา String เปน I love Chiang Mai
ผลลพั ธทีไ่ ดจากการสลบั จะเปน Mai Chiang love I
157
เรม่ิ ตนการเขยี นโปรแกรมดวย Java intro. to Java (FEU.faa)
158
เราไดเ รยี นรูถึงโครงสรางหลักของการเขียนโปรแกรมโดยทั่วไปจากบทกอ น ๆ เราไดเรยี กใช class intro. to Java (FEU.faa)
ตาง ๆ (บาง class) ท่ี Java มีใหใ นการเขียนโปรแกรม รวมไปถงึ การสรา ง object จาก class String
และ class StringBuffer ในบทนี้เราจะมาทาํ ความเขา ใจในเร่อื งของการสราง class การสรา ง object
จาก class ทเ่ี ราสรางขน้ึ การนาํ เอา class มาชว ยแกโ จทยและปญ หาทางดา นคอมพิวเตอร
หลงั จากจบบทนี้แลว ผอู า นจะไดร บั ทราบในเรือ่ งของ
o Class และ Object
o การสรา ง constructor
o การสราง method
o การ overload method
o การสรา ง object จาก class
o การใช attribute ตาง ๆ ของ class
o การสราง nested class
o การสราง และการเรียกใช package
5.1 Class และ Object
เราไดเ หน็ จากบทกอน ๆ วา เราตอ งกําหนดโปรแกรมท่เี ราเขียนข้นึ ดวยคําวา class เสมอ แตเราไมไ ด
พดู ถึงเลยวา class คอื อะไร โดยท่วั ไปการเขียนโปรแกรมดวยภาษาท่เี รยี กกนั วา Object-Oriented
Programming (OOP) นัน้ คาํ วา class มกั จะหมายถงึ คุณลกั ษณะ หรอื คณุ สมบัติ (prescription)
ของวตั ถใุ ดวตั ถหุ นึ่ง (ท่เี กดิ จาก class นน้ั ๆ) ซงึ่ ถา พดู แบบภาษาชาวบานท่ัว ๆ ไปเราอาจเรียก class
ดงั กลา ววา เปน แมแบบของ class (อนื่ ๆ ท่ตี ามมาก็ได) หรอื วา เปนตัวกาํ หนดคณุ สมบตั ิของ object
ท่ีไดถ กู สรางขึ้น
ถาเรามองไปรอบ ๆ ตวั เรา เราจะเหน็ วัตถหุ ลากหลายชนดิ เชน เกา อี้ keyboard ถวยกาแฟ และอะไร
อน่ื ๆ อีกมากมาย ซึ่งวตั ถหุ ลายชน้ิ มีรปู รางหนาตาเหมือนกนั มกี ารใชสอยท่ีคลา ย หรอื เหมอื นกัน
เชน เกา อ้มี ีสีข่ า หรือสามขา มพี นกั พงิ หรือไมม ีพนักพิง แตการใชงานเหมอื นกันคอื เอาไวน ง่ั หรือ
อกี ตวั อยางหนงึ่ เชน รถยนต มสี ลี่ อ ขบั เคลอ่ื นไปไดทั้งขางหนา และขางหลัง ตองใชน าํ้ มนั เปน
เชือ้ เพลิง มีสภี ายนอกท่ตี างกัน แตมคี ณุ สมบตั ิที่เหมอื นกนั คอื เอาไวเดินทางไปยงั ทต่ี าง ๆ และ
โดยทั่วไปแลว ผขู บั ขีส่ ว นใหญจะไมร ถู งึ การทํางานของเคร่ืองยนตทีอ่ ยูภายใน รูแ ตเ พยี งขอมลู ท่ี
จําเปน บางสวน เชนเปดประตอู ยางไร start เครือ่ งยังไง เขา เกยี รอ ยางไร อยางนเี้ ปน ตน การเขียน
โปรแกรมในรูปแบบของ OOP ก็เหมือนกนั ถาเราพัฒนาโปรแกรมใดสกั โปรแกรมหนึง่ ใหผอู น่ื ใช ผใู ช
กลุมนั้นไมจ ําเปน ทจี่ ะตองรูวา เราเขยี นอยา งไร ควรรูเพยี งแตวา จะใชสวนตาง ๆ ที่เราเขียนข้ึนอยางไร
และนํากลบั ไปใชใหมไ ดอยางไร (เหมอื นเชนท่ีเราเรยี กใช method ตาง ๆ จาก class String เราไมรู
วา เขาเขยี น code อยางไร รูแตวา ใชงานอยางไร)
ถามองกลับไปดู class String ท่เี ราใชในบทท่ีสี่นัน้ จะเห็นวาเราสามารถที่จะใช method ตา ง ๆ ท่ีมี
โดยไมมกี ารจาํ กัดจํานวนครั้งท่ีใช โปรแกรมตวั ไหนเรยี กใชก็ได การทํางานกย็ งั คงเหมอื นเดิม
ผลลัพธของการเรยี กใชก ็เหมอื นเดิม object ท่มี าจาก class String ไมวา จะเปน ตัวไหน เรากส็ ามารถ
ที่จะใช method ตา ง ๆ กับ object เหลา นีไ้ ด ในการออกแบบ class นั้นโดยทัว่ ไปเราตองออกแบบ
ใหเ หมาะสมกับงานของเรา เชนถา โปรแกรมของเราตอ งวนุ วายกบั คนเรากอ็ าจออกแบบให class ของ
เรามคี ุณสมบัติและคณุ ลักษณะ ทเี่ กยี่ วของกับคน เชน มชี อ่ื นามสกลุ ที่อยู สถานะภาพ อาชพี และ
อะไรอืน่ ๆ ทํานองนี้ โดยท่วั ไปการออกแบบ class น้ันมสี วนประกอบที่จาํ เปน และ สําคญั อยสู องสวน
ใหญ ๆ คอื
เรมิ่ ตนการเขียนโปรแกรมดว ย Java intro. to Java (FEU.faa)
o Field หมายถงึ ตวั แปรสาํ หรบั การเก็บขอ มลู ของ object ท่บี งบอกถงึ ความเหมือน หรือ ความ
แตกตา งกนั ของ object ทเี่ กดิ มาจาก class เดยี วกัน และ field ยังเปนที่เกบ็ ผลลพั ธของการ
ประมวลผลของ class
o Method หมายถงึ กระบวนการ (operation) ตา ง ๆ ทเี่ ราสามารถทําไดก บั object นน้ั ๆ ของ
class ซงึ่ กระบวนการตาง ๆ ที่ทําไดสว นใหญจ ะกระทาํ กับ field ทมี่ อี ยใู น class
Field สามารถที่จะกาํ หนดใหเ ปนขอ มูลไดท กุ ชนิด รวมไปถึงการเปน ตัวอางอิง (reference) ถงึ
object ที่มาจาก class อนื่ (เชน ตัวแปรทมี่ ีชนดิ เปน String หรือ array ที่เราไดพ ูดถึงกอ นหนาน้)ี
หรอื แมแ ตกระทั่งการเปนตัวอางองิ ถึง class ของมันเอง
Method จะประกอบไปดว ยช่ือของ method และชดุ คาํ ส่งั ตา ง ๆ ทีต่ วั มนั เองมหี นาที่ในการทาํ ตาม
คณุ ลักษณะท่ีไดถูกออกแบบไว ซ่งึ โดยสวนใหญจะกระทํากับ field (แตก ไ็ มจําเปน เสมอไป เชนใน
กรณขี อง method main())
เพือ่ ใหเ หน็ ภาพชัดเจนยงิ่ ขน้ึ เรามาลองออกแบบ class ข้ึนมาสกั class หนึง่ ทเี่ ก่ียวขอ งกับ Student
field class name Instance variable
Method Class variable
class Student {
String id; Constructor
String firstname; Parameter list
String lastName;
String dateOfBirth;
static int count = 0;
Student(String iden, String fName, …
…
}
public int getCount() {
return count;
}
//method ตวั อ่นื ๆ ทเ่ี หลืออยู
…
…
}
ภาพที่ 5-1 ตวั อยา งการสราง class Student
Class Student ที่เราสรา งขน้ึ ประกอบไปดว ยสวนประกอบสองสว นดังทีไ่ ดกลา วไปแลว คอื สวนท่ี
เปน field และสว นทีเ่ ปน method ซึง่ ภายในสวนสองสวนน้ี ยงั มสี วนประกอบอื่นอีกทีม่ ีความสาํ คัญ
ตอการออกแบบ และการใช class
[Class Modifier]
ในการสราง class น้ันเราสวามารถทจี่ ะกาํ หนดให class ที่เราสรางข้นึ มคี ุณลักษณะ (หรือขอ กําหนด)
ตามทเี่ ราตอ งการไดดว ยการใช class modifier
• public – เปน การกําหนดใหการเขา หา class เปนไปไดต ลอดเวลา นน่ั กค็ ือ เราสามารถสรา ง
object จาก class น้ไี ดท กุ เมื่อ
• abstract – class ที่ประกาศเปน abstract เปรียบเสมอื นวา เปน class ท่ียังไมส มบรณู และ
เราไมส ามารถสรา ง object จาก class นีไ้ ด โดยสว นใหญแ ลว การประกาศแบบนม้ี กี าร
160
บทท่ี 5: Objects และ Classes intro. to Java (FEU.faa)
กําหนดให class ดังกลาวมี method ทเี่ ปน abstract ซ่งึ ตอ งมกี ารสรา งจาก subclass
(class ท่ีเกิดจาก class)
• final – เปน class ทไี่ มสามารถมี subclass ได
• strict floating point – เปน class ที่มีการใชการประมวลของเลขที่มีจดุ ทศนยิ มอยา ง
เครงครัด
class ไมส ามารถเปน ไดท ั้ง final และ abstract พรอม ๆ กัน เราจะกลับมาดถู ึง modifier เหลานใ้ี น
บทตอ ๆ ไป
[Field Modifier]
เชน เดียวกับ class, field ก็สามารถท่จี ะมี modifier เปน ตัวกาํ หนดคณุ ลกั ษณะไดเ ชน กัน
• access modifier – เชน private, package, protected, และ public
• static – เปน การกาํ หนดให field เปน filed ทใี่ ชรวมกนั ของ object
• final – เปน การกาํ หนดให field เปนคา ท่ีไมสามารถเปลีย่ นแปลงได
• transient – เกี่ยวขอ งกับการ serialization ของ Object ซึง่ เราคงไมพ ูดถงึ
• volatile – เก่ยี วของกบั การประสานเวลาของ object (synchronization) ซง่ึ เราจะพูดถงึ ใน
บทที่ 9
field ไมสามารถเปนไดท ั้ง final และ volatile พรอม ๆ กัน
5.1.1 Object และ องคป ระกอบของ object
ความหมายของ Object ตามนยิ ามทก่ี าํ หนดไวจ าก Java คอื "ซอฟตแ วรทป่ี ระกอบไปดว ยตัวแปร
และ method" และ object จะมสี ถานะอยูสองสถานะ คอื 1). สถานะภาพ หรือ คณุ ลักษณะ (State)
และ 2). กระบวนการ หรือ การกระทํา (Behavior) ตวั อยา งเชน สนุ ขั มี state คือ ช่ือ สี พันธ มีความ
หวิ และมี behavior คือ เหาได กระดกิ หางได ไลกดั ได เปน ตน
Object ท่ีเกดิ มาจาก class น้นั เราเรียกกนั วา instance ของ class และ object นจี้ ะมีสว นประกอบท่ี
class มใี ห คอื ตวั แปรตาง ๆ ทอ่ี ยูใน class ตัวแปรเหลานจ้ี ะมขี อ แตกตางกนั คอื อาจเปนตัวแปรที่
เปน class variable และอาจเปนตัวแปรทเี่ ปน instance variable
หลงั จากทเี่ ราสรา ง object แลว object จะไดรับ copy ของตวั แปรท่ี class มใี ห ซงึ่ ตัวแปรเหลา นจี้ ะ
เปน ตวั บงบอกวา object ตวั ไหนแตกตางกันอยา งไร คาของตัวแปรของ object แตละตวั จะมีคา
เหมอื นหรือแตกตา งกันนั้นขนึ้ อยูก ับการกาํ หนดของโปรแกรมเอง เชน ถา เราสรา ง object สองตวั จาก
class Student ข้นึ มาใชง าน object สองตัวนจ้ี ะมี copy ของตวั แปรทง้ั ส่ตี วั ของมันเอง เราเรยี กตัว
แปรเหลา นีว้ า instance variable
สว นตัวแปรอีกชนิดหนึง่ คอื class variable นน้ั กําหนดไววา object ทุกตวั ทเี่ กดิ จาก class จะใชตัว
แปรชนดิ น้รี วมกนั และตัวแปรนส้ี ามารถท่ีจะกําหนดและสรางข้นึ มาใชได ถงึ แมวาจะไมมี object
เกิดขนึ้ จาก class น้ีก็ตาม เพราะวา ตวั แปรนีเ้ ปน ของ class ดงั น้นั ทงั้ class และ object ก็สามารถที่
จะใชม ันได ถาคา ของตวั แปรนเ้ี ปลี่ยนไป object หรือ class ทอ่ี า งการใชถ ึงตวั แปรตวั นี้ก็จะไดคาใหม
ทีเ่ ปลี่ยนไป ซึ่งตรงกนั ขามกับตวั แปรทีเ่ ปน instance variable ถาหาก object ตัวไหนเปลย่ี นคา ของ
ตัวแปรใด ๆ (copy) คา ทเ่ี ปลย่ี นไปจะไมม ผี ลตอตัวแปรใด ๆ ใน object ตวั อนื่ การประกาศใหตัวแปร
ใดๆ ก็ตามเปน class variable นน้ั เราตองใชคําสั่ง static นําหนา ตัวแปรน้นั เสมอ ดังท่ไี ดแสดงใน
ภาพท่ี 5-2
161
เรม่ิ ตน การเขยี นโปรแกรมดว ย Java
class Student { Object ทุกตัว share intro. to Java (FEU.faa)
static int count = 0; ตวั แปร count
0
String id;
String firstname; Joe
String lastName; id
String dateOfBirth;
firstNAme
lastName
dateOfBirth
ทั้ง Joe และ Jon มี copy
ของตวั แปรเหลานี้
Jon
id
firstNAme
lastName
dateOfBirth
ภาพที่ 5-2 การใชตัวแปรแบบ class variable และแบบ instance variable
ตวั แปรทงั้ สองชนิดมกี ารใชที่แตกตา งกนั และตา งกม็ ีความสาํ คญั ท้ังคู โดยทว่ั ไปการใช class
variable น้นั นยิ มใชใ นกรณีท่ีเราตองการท่ีจะเก็บคาทเ่ี ปนคาท่ี object ทั้งหมดตอ งใชร ว มกนั เชน
คา คงท่ีตา ง ๆ ทีม่ คี วามจาํ เปน ใน class น้ัน ๆ ตัวอยางของเราใช count เปนตัวแปรท่ีใชรว มกนั
ระหวา ง object ตา ง ๆ สวนตัวแปรท่เี ปน instance variable นน้ั มคี วามจาํ เปน อยางมากในการ
ออกแบบ class ตา ง ๆ ทัง้ น้ีเพราะตวั แปรชนิดนจ้ี ะเปนผูกาํ หนดความแตกตา งระหวา ง object ตา ง ๆ
ทีไ่ ดถ กู สรา งข้ึนจาก class นน้ั ๆ เชน object จาก class Student ทถ่ี กู สรา งข้นึ อาจมี id ทไี่ ม
เหมอื นกัน ชือ่ ตน และ ชอ่ื สกุลที่แตกตางกนั วนั เดอื นปเ กดิ ที่ไมเ หมอื นกัน อยางนีเ้ ปน ตน
[ส่งิ ที่ตอ งคิดเมื่อออกแบบ class (เมื่อสราง object)]
เนอื่ งจากวา เราตองสรา ง object ในการทาํ งานตา ง ๆ ดังน้ันในการออกแบบ class สง่ิ ที่เราจําเปน ตอ ง
คํานึงถึงกค็ อื คณุ สมบัตขิ อง object ทเี่ ราสรางข้ึน
ส่งิ ที่ object รู (know) – instance variable
สงิ่ ท่ี object ทํา (do) - method
เชน
class Song { know
title; do
artist;
setTitle()
setArtist()
playSong()
…
}
ภาพท่ี 5-3 ส่ิงทีค่ วรคํานึงในการออกแบบ class
162
บทท่ี 5: Objects และ Classes
5.1.2 ขอแตกตา งระหวาง class กบั object
class object intro. to Java (FEU.faa)
เปนแมแ บบทม่ี สี มาชกิ ทั้ง data และ ตองเกิดมาจาก class ใด class หน่งึ
method มตี ัวตนขณะโปรแกรมกําลัง execute
ไมม ีตวั ตนขณะท่ีโปรแกรมกาํ ลัง execute สามารถเปลี่ยนแปลงคา ของ data ขณะ
ไมมกี ารเปล่ยี นแปลงขณะโปรแกรม
execute
execute
5.2 Method (ส่ิงท่ี object ทําได)
จากแผนภาพท่ี 5-1 เราจะเหน็ วามี method อยใู น class Student ของเรา (บางสวน) method เปน
กระบวนการ (ท่ีรวบรวมชุดคาํ ส่งั ) ทเ่ี ราสามารถเรียกใชใหท ํางานตาง ๆ ใหเรา ซึ่งอาจเปนการทาํ งาน
ที่เกย่ี วขอ งกับ ตวั แปรทีอ่ ยใู น class หรือกระบวนการอื่น ๆ ทจ่ี าํ เปน ของ class น้นั ๆ และเชนเดียวกนั
กบั ตัวแปรทไ่ี ดกลา วไวกอนหนา นี้ method ก็ไดถ ูกแบงออกเปนสองชนิด คือ class method และ
instance method
Class method กค็ ือ method ทส่ี ามารถท่ีจะไดรบั การประมวลผลถงึ แมว า จะไมมี object อยูเลย ถา
เรามองยอนกลับไปดู method main() ของเรา เราจะเหน็ วา ไมม ี object ใด ๆ เกิดจาก class ที่มี
method main() อยเู ลย และการประกาศใช class method ก็เชนเดยี วกันกับ class variable เรา
ตอ งใชคาํ สั่ง static นําหนาเสมอ
สว น instance method นั้นเปน method ที่ตอ งมกี ารใชร วมกันกับ instance variable ทั้งน้ีเพราะวา
method ประเภทนถี้ กู สรา งข้ึนมาจาก class เดียวกนั กบั ท่ี object ถกู สรา งขึน้ มา การกระทาํ ใด ๆ ก็
ตามตองทาํ ผา น instance method เทาน้ัน
5.2.1 การเขาหาตัวแปร และ method ของ class
ในการท่จี ะเขา หาตัวแปรหรือ method ของ class นัน้ ไมวา จะเพอื่ อะไรก็ตามแต เราจะตองเขา หาผาน
ทาง object ของ class ตามดว ย . (dot) และตามดว ยชอ่ื ของตัวแปร หรือ ชอ่ื ของ method
เชน
studentA.firstName;
หรอื
studentB.getAge();
ในตอนนเ้ี ราจะดูเพียงแคว ธิ กี ารเขาหา แตต อ ไปเราจะดูเรือ่ งการกาํ หนดนโยบายของการเขาหาตัว
แปร หรอื method เหลา น้ี ถา มี method หรือ ตัวแปรอยเู ราก็เขาหาแบบทไ่ี ดกลาวมาแลว Java จะ
ฟองดว ย error ถา หากอางถงึ ตัวแปรหรอื method ทีไ่ มไ ดถกู สรางขน้ึ เพื่อใหเหน็ ภาพของการสราง
class รวมไปถึงสว นประกอบตาง ๆ ของ class เรามาดู class Student ท่ไี ดถ กู สรา งข้นึ เพ่ือเปน
ตัวอยาง
1: /**
2: Simple class for student
3: */
4:
5: import java.util.*;
6: import java.text.*;
7: import static java.lang.System.out;
8:
9: class Student {
10: String id; //student id
11: String firstName; //student's first name
12: String lastName; //student's last name
13: String dateOfBirth; //student's date of birth
14: static int count = 0;//number of object created
15: Calendar cal; //use to calculate age
16: SimpleDateFormat dateFormatter; //for date format
17: int ADJUST_TIME = 0; //for time differences
18:
163
เริ่มตน การเขยี นโปรแกรมดว ย Java intro. to Java (FEU.faa)
19: //class constructor to initialize fields to given values
20: Student(String iden, String fName,
21: String lName, String dOfB) {
22: id = iden;
23: firstName = fName;
24: lastName = lName;
25: dateOfBirth = dOfB;
26: count++;
27: }
28:
29: //returns count
30: public int getCount() {
31: return count;
32: }
33:
34: //returns student's id
35: public String getId() {
36: return id;
37: }
38:
39: //returns student's first name
40: public String getFirstName() {
41: return firstName;
42: }
43:
44: //returns student's last name
45: public String getLastName() {
46: return lastName;
47: }
48:
49: //returns student's date of birth
50: public String getDateOfBirth() {
51: return dateOfBirth;
52: }
53:
54: //calculates student's age
55: public String getAge() {
56: //input is in year of Christ, we need to set this machine's
57: //locale to us and accommodate lost time for the calendar
58: Locale.setDefault(new Locale("en_US"));
59: ADJUST_TIME = 1970;
60:
61: cal = Calendar.getInstance();
62: //make sure we have the right date format
63: dateFormatter = new SimpleDateFormat("dd/MM/yyyy");
64: //milliseconds when this person was born
65: long dob = 0L;
66: try {
67: //must be in a try block
68: dob = dateFormatter.parse(dateOfBirth).getTime();
69: }
70: catch(ParseException ex) {}
71:
72: //get total time passed since this person was born
73: long elapsedTime = Math.abs(dob - System.currentTimeMillis());
74: //convert it to current calendar's milliseconds
75: cal.setTimeInMillis(elapsedTime);
76:
77: long ageInDays = elapsedTime / (1000*60*60*24);
78:
79: //extract number of years, months, and days
80: int years = cal.get(Calendar.YEAR) - ADJUST_TIME;
81: int months = cal.get(Calendar.MONTH);
82: int days = cal.get(Calendar.DAY_OF_MONTH) - 1;
83:
84: return new String("("+ ageInDays + " days) " +
85: years + " years " +
86: months + " months " +
87: days + " days");
88: }
89:
90: //displays students' info to screen
91: public void display() {
92: out.printf("%s %s %s", getId(), getFirstName(), getLastName());
164
บทท่ี 5: Objects และ Classes intro. to Java (FEU.faa)
93: out.printf(" [Age: %s]%n", getAge());
94: }
95: }
เราไดก าํ หนดให class Student มี field อยทู ง้ั หมด 5 field คอื id, firstName, lastname,
dateOfBirth, และ count โดยท่สี ีต่ ัวแรกเปน instance variable ทเี่ อาไวเก็บขอมูลโดยเฉพาะของ
object แตละตวั ทไ่ี ดถ กู สรางขนึ้ และตวั สดุ ทายเปน class variable ทเี่ อาไวเกบ็ จํานวนของ object
ท่ไี ดถ ูกสรา งขึ้น
เรายังไดสราง method อีก 7 ตวั ซ่งึ มหี นา ทใ่ี นการทํางานที่ตางกนั โดยเฉพาะ method ท่ีมีชื่อ
เหมอื นกนั กบั class น่นั ก็คือ method Student
Student(String iden, String fName, String lName, String dOfB) {
id = iden;
firstName = fName;
lastName = lName;
dateOfBirth = dOfB;
count++;
}
Student() เปน method พเิ ศษที่มชี ่ือเรยี กกันโดยท่วั ไปวา เปน constructor ของ class ซ่งึ
constructor น้สี วนใหญจะทาํ หนา ทีใ่ นการกาํ หนดคา เบอื้ งตนใหกบั object ท่ีไดถ ูกสรา งขึ้นจาก
class เชน กําหนดคา ใหกับ field ทุก field หรือบาง field (ท้งั นตี้ อ งแลวแตก ารออกแบบการทาํ งาน
ของ constructor นัน้ ๆ) ตวั อยางของเรากําหนดให constructor ทําการกําหนดคา ใหก ับ field ทกุ
field (ยกเวน class variable ทช่ี ือ่ count) ใหมคี า เปนไปตามคาทีไ่ ดรบั เขา มาจากตวั แปรทอี่ ยใู น
parameter list แต constructor จะมคี ณุ สมบัตพิ ิเศษคอื การกาํ หนดคา น้ันจะไดร ับการกระทาํ โดย
อตั โนมัติ เราไมตอ งเรียกใช constructor การเรยี กใช constructor น้ี Java จะเปนผเู รยี กใหใ นตอนที่
เราสรา ง object ขึน้ มา กอ นที่เราจะพูดถงึ constructor และการถกู เรยี กใชงานโดยอตั โนมตั ินั้นเรามา
ดูกันถงึ method และ วิธกี ารสราง method รวมไปถึงการสงคา ใหกบั method และการสงคา กลบั
ของ method
5.2.2 การสราง method
ในการสรา ง method น้ันเราจะตองกําหนดชอื่ ใหก บั method กาํ หนด parameter (ถาม)ี กําหนดการ
สง คากลบั ของ method (ถาม)ี โดยทวั่ ไป method ไดถ ูกแบง ออกเปนสองแบบ คอื
o Method ท่ีสงคากลับใหแกผทู เี่ รียกใช method
o Method ท่ไี มมีการสงคา ใด ๆ กลบั ไปใหผ เู รยี ก
โครงสรา งของ method โดยทว่ั ไปจะมีรปู แบบดังนี้
165
เร่ิมตน การเขียนโปรแกรมดวย Java
ชนิดของคา ทีส่ งกลับ ชนิดของคาที่สงกลับ ชื่อของ method Parameter (ถาม)ี intro. to Java (FEU.faa)
เปน ชนิดไหนก็ได
ใชค าํ สง่ั void ถา ไมมี
คาท่ตี อ งสง กลับ
returnType methodName( arg1, arg2, …, argn ) {
// body of method
…
…
}
ชุดคําสง่ั ตา ง ๆ ท่ี method ตวั นีม้ อี ยู (body of method)
ภาพท่ี 5-4 โครงสราง method
กอ นทีเ่ ราจะหยบิ เอา method getAge() จาก class Student มาดกู ันเพอื่ ใหเกดิ ความเขา ใจในเรอื่ ง
สว นประกอบตา ง ๆ ที่มอี ยูใน method ทว่ี า นี้ เราจะมาดกู ันถึง modifier ตาง ๆ ของ method
[Method Modifier]
• access modifier – เชน private, protected และ public
• abstract – เปน method ท่ไี มมีชดุ คาํ สั่งใน class นีแ้ ตจ ะมีอยูใน subclass
• static – เปน method ท่ีทํางานสําหรับ class ทงั้ หมดไมใ ช object ใด object หน่งึ ทเี่ กิด
จาก class
• final – เปน class ที่ไมส ามารถเปลยี่ นแปลงโดย subclass ได
• synchronized – เปน การประสานเวลาของการทํางานของ object ทใ่ี ชทรพั ยากรรว มกัน
• native – เกย่ี วขอ งกับการเรียกใชชุดคาํ สง่ั ในรูปแบบอืน่
• strict floating point – ดเู รอ่ื ง filed modifier
method ทีเ่ ปน abstract ไมสามารถเปน static, final, synchronized, native หรอื strict ไดและ
native method ไมสามารถเปน strict ได เรามาดู method getAge() กนั วามสี ว นประกอบใดบาง
public String getAge() {
//input is in year of Christ, we need to set this machine's
//locale to us and accommodate lost time for the calendar
Locale.setDefault(new Locale("en_US"));
ADJUST_TIME = 1970;
cal = Calendar.getInstance();
//make sure we have the right date format
dateFormatter = new SimpleDateFormat("dd/MM/yyyy");
//milliseconds when this person was born
long dob = 0L;
try {
//must be in a try block
dob = dateFormatter.parse(dateOfBirth).getTime();
}
catch(ParseException ex) {}
//get total time passed since this person was born
long elapsedTime = Math.abs(dob - System.currentTimeMillis());
//convert it to current calendar's milliseconds
cal.setTimeInMillis(elapsedTime);
166
บทที่ 5: Objects และ Classes
long ageInDays = elapsedTime / (1000*60*60*24); intro. to Java (FEU.faa)
//extract number of years, months, and days
int years = cal.get(Calendar.YEAR) - ADJUST_TIME;
int months = cal.get(Calendar.MONTH);
int days = cal.get(Calendar.DAY_OF_MONTH) - 1;
return new String("("+ ageInDays + " days) " +
years + " years " +
months + " months " +
days + " days");
}
ถา เราแยกสวนประกอบตา ง ๆ ออก เรากจ็ ะไดขอมูลดงั นี้
ชนิดของคา ท่ีสงกลบั String
ชื่อของ method คอื getAge
Parameter ไมม ี
ชุดคาํ สัง่ เราจะกลบั มาดกู ระบวนการตา ง ๆ ใน method นอี้ ีกครัง้ หนงึ่
ถา สังเกตใหดีจะเห็นวา ดานหนา สุดของ method getAge() จะมคี าํ วา public อยู คาํ วา public น้จี ะ
เปน ตัวบอกใหร ูวาใครกไ็ ดท ไ่ี ดถกู สรา งมาจาก class นี้สามารถเรียกใช method นไ่ี ด (โดยไมม ี
ขอจาํ กดั ใด ๆ)
สว นประกอบที่สําคัญอีกสว นหนงึ่ ก็คอื คาํ วา return ในบรรทัดสุดทาย เนือ่ งจากวา method
getAge() ของเราตองสง คากลับ ดงั น้นั เราจึงจําเปน ท่จี ะตองบอกให Java รวู าเรามีคาท่ีตองการ
สง กลบั ดังท่ไี ดประกาศไว ถาหากวา เราไมมกี ารใช return พรอมท้ังคา ที่ตองการสงกลับ Java ก็จะ
ฟองดวย error ตอนทีเ่ รา compile โปรแกรม
เรามาลองดู method ท่ไี มมกี ารสง คา กลับใน class Student ของเรา ซ่ึงมีอยูเ พยี งตัวเดยี ว คอื
public void display() {
out.printf("%s %s %s", getId(), getFirstName(),
getLastName());
out.printf(" [Age: %s]%n", getAge());
}
ชนิดของคาทส่ี ง กลบั ไมม ี
ชอื่ ของ method คือ display
Parameter ไมม ี
ชดุ คาํ สัง่ คอื
out.printf("%s %s %s", getId(), getFirstName(),
getLastName());
out.printf(" [Age: %s]%n", getAge());
Method display() ทําหนาท่ีเปน เพียงตวั แสดงขอ มูลของ object ท่เี กิดจาก class Student ออก
ทางหนา จอ โดยการเรียกใช method อ่ืน ๆ ทม่ี อี ยใู น class Student การที่จะให method ไมตองสง
คา กลับนน้ั เราตอ งใช คาํ วา void นาํ หนา ชอื่ method เสมอ และ method ท่ีมคี าํ วา void นาํ หนา ตอง
ไมม คี าํ วา return ใด ๆ ที่มคี า ในการสง กลบั ยกเวน คาํ วา return ท่ีตามดว ย ; (semicolon) เทา นั้น
เชนถา เราใช void เรากส็ ามารถที่จะใช return ตามดวย ; หรือไมใชเ ลย อยางใด อยา งหน่งึ
เพราะฉะนั้น method display() ท่เี ห็นก็สามารถทจ่ี ะเขยี นไดอ กี แบบหน่งึ ดงั น้ี
public void display() {
out.printf("%s %s %s", getId(), getFirstName(), getLastName());
out.printf(" [Age: %s]%n", getAge());
return ;
}
167
เรมิ่ ตน การเขียนโปรแกรมดว ย Java
ขอ แตกตางระหวาง method ทีส่ งคา และ method ท่ไี มสงคา
method ทสี่ งคา method ท่ไี มสง คา intro. to Java (FEU.faa)
มคี าํ วา return และ คาที่ตองสง กลบั ไมจาํ เปน ตองมีคําวา return แตถ ามจี ะตอ ง
ขึ้นตน method ดว ยชนิดของขอมูลทตี่ อ ง
ตามดวย ; อยางเดียวเทานนั้
สง กลับ ข้ึนตน method ดว ยคําวา void เสมอ
5.2.3 กระบวนการทเี่ กดิ ขน้ึ เม่ือมีการใช parameter list
เราลองมาดูโปรแกรมตัวอยางท่ีมีการสรา ง method ท่ีมีการใช parameter list กอนท่ีเราจะกลบั มาดู
รายละเอียดของ class Student อกี คร้งั หน่งึ
1: /**
2: Parameter list demo.
3: */
4:
5: import static java.lang.System.out;
6:
7: class Parameters {
8: public static void main(String[] args) {
9: //radius of a circle
10: double radius = 2.5;
11:
12: //calling method findArea() with radius
13: double area = findArea(radius);
14:
15: out.printf("Area of a circle is %5.2f ", area);
16: }
17:
18: //calculate an area of a circle with radius: r
19: public static double findArea(double r) {
20: return Math.PI * Math.pow(r, 2.0);
21: }
22: }
โปรแกรม Parameters.java สรา ง method ท่เี ราเรยี กวา class method ขน้ึ มาใชง านหนง่ึ ตวั (การ
ประกาศให method เปน class method ก็เหมอื นกบั การประกาศใหต วั แปรเปน class variable เรา
ตองใชคําวา static นําหนา) ซงึ่ method น้ีมหี นา ท่ีในการคาํ นวณหาพื้นทขี่ องวงกลมทมี่ รี ัศมที ่ี
กําหนดไวใ นตวั โปรแกรม (ในทีน่ คี้ อื 2.5) method findArea() มี Parameter หนงึ่ ตวั ทม่ี ชี นดิ เปน
double และจะสงคา ของพืน้ ทท่ี คี่ ํานวณไดกลบั ไปใหผ ูเรยี ก ซ่งึ ในท่ีน้ีคอื class Parameters การ
เรยี ก method findArea(() นัน้ เราเรียกดว ยประโยค
double area = findArea(radius);
ซึ่งเมอ่ื Java เห็นการเรียกเชนนี้ Java ก็จะไป execute method findArea() ดว ย parameter ท่มี ี
ชนดิ เปน double และสงคา 2.5 ไปให หลงั จากท่ีคํานวณคาพืน้ ท่ไี ดแ ลวก็จะสง กลับออกมา และ
นําไปเก็บไวใ นตัวแปรช่ือ area ภาพท่ี 5-5 แสดงการสงคา ผา นทาง parameter list
168
บทที่ 5: Objects และ Classes
class Parameters { intro. to Java (FEU.faa)
public static void main(String[] args) {
double radius = 2.5;
double area = findArea(radius); คา ของ radius จะถูกสง
… เขา มาไวใ นตัวแปร r
…
}
…
…
ชนิดของคาทีส่ ง กลับ public static double findArea(double r) {
ออกมา ตองเปน ชนิด return Math.PI * Math.pow(r, 2.0);
เดยี วกนั
}
คาท่ไี ดจากการคํานวณจะถกู
สงไปให ตัวแปร area
ภาพท่ี 5-5 การสง parameter ใหกับ method และการสง คา กลับออกจาก method
การสง คาผา นทางตวั แปรทอี่ ยใู น parameter list นน้ั มอี ยสู องแบบคือ 1) การสง ท่ีเรียกวา pass-by-
value หรอื การสง เฉพาะคา เขาไปใน method นนั้ ๆ และ 2) การสงแบบทีเ่ รียกวา pass-by-
reference การสงคา ใน Java จะเปนการการสง คาเปน แบบ pass-by-value เทาน้ัน ซึ่งไดแ สดงไวใน
ภาพที่ 5-6
class PassByValue { total
public static void main(String[] args) { 10
int total = 10;
… copy ของ total
… 10
int newTotal = increment(total);
…
}
…
การประมวลผลทํา public static int increment(int sum) {
กับ copy ของ sum += 10;
total
return sum;
} ตวั แปร sum อาง
ถึง copy ของ
ภาพท่ี 5-6 การสง คา แบบ pass-by-value
total ทีอ่ ยูใน
main()
ตัวแปร total ที่อยใู น method main() น้ันจะไมไดรับผลกระทบจากการเปล่ียนคา ท่เี กดิ ขึ้นภายใน
method increment() ทั้งน้กี ็เพราะวา กระบวนการท่เี กดิ ขึน้ ไมไดก ระทาํ กับตวั แปร total แตเ ปน การ
กระทาํ กบั copy ของ total
การสง คาไปยงั method แบบ pass-by-value น้คี า ทส่ี งเขา ไปจะถกู นาํ ไปใชภ ายในตัว method
เทาน้ัน การเปล่ยี นแปลงใด ๆ ทเี่ กดิ ขน้ึ จะไมมผี ลกระทบกบั ตวั แปรท่เี ปน เจาของคา นั้น ภายนอก
method เลย ลองมาดตู ัวอยา งโปรแกรมการสงคาแบบ pass-by-value กัน
1: /**
169
เร่ิมตนการเขียนโปรแกรมดว ย Java intro. to Java (FEU.faa)
2: Passing parameter to method: pass by value
3: */
4:
5: import static java.lang.System.out;
6:
7: class PassByValue {
8: public static void main(String[] args) {
9: int total = 10;
10:
11: out.println("Before calling: total is " + total);
12:
13: //calling method increment() with total as a parameter
14: out.printf("Value returned from increment() is %d%n",
increment(total));
15:
16: out.println("After calling: total is " + total);
17: }
18:
19: //method increment() with sum as an argument
20: //add 10 to sum then return sum to the caller
21: public static int increment(int sum) {
22: sum += 10;
23:
24: return sum;
25: }
26: }
ผลลัพธทีไ่ ดจ ากการ run คือ
Before calling: total is 10
Value returns from increment() is 20
After calling: total is 10
increment() ถกู เรยี กภายใน main() จากประโยค System.out.println("Value returns from
increment() is " + increment(total)); ซ่งึ มกี ารสง คา ของ total ไปให (ซ่งึ มีคาเปน 10) คา น้ี
ถกู นาํ ไปใชใ น increment() ผานทางตัวแปรที่ชือ่ วา sum ภายใน increment() ตวั แปร sum ถกู
เปลย่ี นคาดวยการนาํ เอา 10 ไปบวกเพ่มิ ทาํ ให sum มคี า เปน 20 ซ่ึงคานีจ้ ะถกู สง กลับไปยงั main()
ทาํ ใหการแสดงผลทางหนา จอมีคา เปน 20 แตหลังจากนนั้ เรากําหนดใหมกี ารแสดงคาของ total อีก
ครง้ั หน่ึง ซึ่งผลลัพธท ไ่ี ดคอื คาของ total ยังคงเปน 10 อยู จะเห็นวาคาของ total ทไ่ี ดรับการ
เปล่ยี นแปลงภายใน increment() (ผา นทางตวั แปร sum) ไมมผี ลตอ ตัวแปร total อยา งใดเลย การ
เปลยี่ นแปลงเกดิ และตายภายใน increment() เทา นั้น เรามาลองดโู ปรแกรมตวั อยางอีกโปรแกรม
หนงึ่
1: /**
2: Passing argument to a method: pass by value
3: */
4:
5: import static java.lang.System.out;
6:
7: class PassByValue2 {
8: public static void main(String[] args) {
9: String myString = "Information Technology";
10:
11: out.println("Before string is: " + myString);
12:
13: changeString(myString); //calling changeString()
14:
15: out.println("After myString is: " + myString);
16: }
17:
18: //method changeString() with a string as an argument
19: //try to change a string
20: public static void changeString(String string) {
21: out.printf("\tInside changeString(): ");
22: out.printf("myString is: %s%n", string);
23:
24: //changing string
25: string = "at Far Eastern College";
26: }
27: }
170
บทท่ี 5: Objects และ Classes
โปรแกรม PassByValue2.java สราง string หนง่ึ ตวั มีขอ ความวา "Information Technology" และ intro. to Java (FEU.faa)
สง string นีไ้ ปให method changeString() ซงึ่ ทําหนาท่ีในการเปล่ียนคาของ string ทสี่ งเขา มาให
เปน "at Far Eastern College" แตหลังจากทเี่ รา run โปรแกรมดู เรากไ็ ดผลลพั ธต ามท่เี หน็ ดานลา ง
นี้
Before string is: Information Technology
Inside changeString(): myString is: Information Technology
After myString is: Information Technology
จะเห็นวาการเปลี่ยนแปลงคาของ string ทสี่ งผา นเขามาน้นั จะเปนเพียงการเปลย่ี นแปลงแบบช่วั คราว
เทาน้นั การเปลย่ี นแปลงเกดิ ข้นึ ภายใน changeString() และไมม ีผลกระทบใด ๆ กับคา ของตัวแปร
myString แตอยางใดเลย
5.2.4 การสง คา อางอิง (Passing object's reference)
การสง คาแบบอางอิงนั้น สง่ิ ท่ีเราสงเขาไปใน method นัน้ ไมใชค า ของตัวแปร (copy) แตเ ปน
ตวั อา งองิ ถึง object นนั้ ๆ โดยตรง เราอาจพูดไดว า สิง่ ทเี่ ราสง ไปนัน้ เปน ท่ีอยู (address) ของ
object นนั้ ๆ ก็ได เรามาลองดูตวั อยางการสง แบบอา งอิงกันในภาพท่ี 5-7
public static void main(String[] args) {
Circle red = new Circle(5.0);
…
…
… ทั้ง red และ Circle object
red.change(red, 2.0); copy ของ red Radius: 5.0
ตา งกอ็ า งถงึ
… copy of red
object เดิม reference
สราง copy
ของ red red
reference copy made
ประโยค c อา งถงึ
copy ของ
c.changeRadius(radius)
ทาํ การเปล่ียนแปลงขอ มลู red
ของ object เดมิ ผา นทาง public Circle change(Circle c, double radius) {
copy ของ red
c.changeRadius(radius);
return c;
}
ภาพท่ี 5-7 การสงแบบอา งอิง
ตวั อยางการสงแบบทีเ่ ห็นในภาพที่ 5-7 น้นั เราสรา ง object จาก class Circle หนึ่งตัว โดยใหม ชี อ่ื วา
red และมี radius เทา กับ 5.0 เราเรียก method change() ผานทาง object red ดว ยการสง object
red และคา ใหมของ radius ไปให เมอ่ื method change() ถกู เรียกดว ย parameter ดังกลาว Java
จะทําการสรา ง copy ใหก บั red และจัดเก็บ copy นีไ้ วท่ี c เน่ืองจากวา ทง้ั red และ c ตางก็อา งถงึ
object ตัวเดียวกัน ดังนัน้ การเปลย่ี นแปลงใด ๆ ที่เกิดข้ึนยอ มมีผลกระทบตอ object ตัวเดิมทีท่ ง้ั red
และ copy ของ red อางถงึ (หรอื เปน ตัวแทนอยู)
ผูอานควรแยกใหออกวา parameter ท่ีเราสงไปให method นน้ั เปนคาอา งองิ ของ object (Object
reference) ไมใ ช object โดยตรงดังนัน้ เราจึงสามารถทจ่ี ะเปล่ยี นแปลง field ตา ง ๆ ของ object ท่ี
ถูกอางถึงได
เราไดสราง method changeRadius() ขน้ึ มาเพื่อใชในการเปลย่ี นคา ของ radius ซ่ึง code ทงั้ หมด
ของโปรแกรมตัวนี้ มดี งั น้ี
1: /**
171
เร่มิ ตนการเขยี นโปรแกรมดวย Java
2: Demonstrate pass-by-reference scheme intro. to Java (FEU.faa)
3: */
4:
5: import static java.lang.System.out;
6:
7: class Circle {
8: private double radius; //a radius of a circle
9:
10: //constructor to initialize radius
11: Circle(double r) {
12: radius = r;
13: out.println("Constructor activated with value of " + radius);
14: }
15:
16: //method to calculate area of a circle
17: public double area() {
18: return Math.PI * radius * radius;
19: }
20:
21: //a method to change radius of a given circle
22: public Circle change(Circle c, double radius) {
23: c.changeRadius(radius); //calling method changeRadius()
24: return c;
25: }
26:
27: //a method to change a given radius
28: private void changeRadius(double r) {
29: radius = r;
30: }
31:
32: //a method to return radius
33: public double getRadius() {
34: return radius;
35: }
36: }
37:
38: //a class to test pass-by-reference scheme
39: class PassByReference {
40: public static void main(String[] args) {
41: //create a red circle with a radius of 5.0
42: Circle red = new Circle(5.0);
43: Circle blue = new Circle(3.5);
44:
45: //calculate area of a red circle
46: double area = red.area();
47: out.printf("Radius of red circle is %.2f%n", red.getRadius());
48: out.printf("Area of red circle is %.2f%n", area);
49:
50: //change radius of a red circle via a blue circle
51: blue.change(red, 2.0);
52: area = red.area();
53: out.printf("Radius of red circle now is %.2f%n", red.getRadius());
54: out.printf("Area of red circle now is %.2f%n", area);
55: }
56: }
เรามี class อยูส อง class โดยที่ class ตวั แรก หรือ class Circle เปน class ที่เอาไวใ ชสรา งวงกลม
ตาง ๆ รวมไปถึง method หรือกระบวนการตาง ๆ ทีเ่ ราตอ งการใชในการเปลี่ยนแปลง หรือกําหนดคา
ใหก บั วงกลมนน้ั ๆ สวน class ตวั ท่สี องเปน class ที่ใชส าํ หรบั การทดสอบ การสราง object จาก
class Circle และตรวจสอบการสง คาแบบ pass-by-reference หลังจากทที่ ดลอง run เรากไ็ ด
ผลลพั ธด งั น้ี
Constructor activated with value of 5.0 ดูคาํ อธิบายใน 5.4 เรอ่ื ง
constructor
Constructor activated with value of 3.5
Radius of red circle is 5.00
Area of red circle is 78.54
Radius of red circle now is 2.00
Area of red circle now is 12.57
จากผลลพั ธเราจะเห็นวาประโยคท่แี สดงคา ของ radius นน้ั แสดงคาไดถ กู ตองท้งั กอ น และหลังการ
เปลย่ี นแปลงคา ของ radius ผูอานควรสังเกตถงึ การเรียกใช method ในบรรทดั ท่ี 51
172
บทที่ 5: Objects และ Classes intro. to Java (FEU.faa)
blue.change(red, 2.0);
เราเรยี ก change() ผา นทาง object ท่ชี ่อื วา blue พรอ มทง้ั สง object red กบั คา 2.0 ไปใหซ่งึ ทาํ ให
การเปล่ียนคา radius ท่ีเกิดขึ้นนั้นเกดิ กบั object red ทั้งนีก้ เ็ พราะวา ภายใน change() เราเรียกใช
changeRadius() ของ object ท่ีสง เขา น่นั กค็ ือ c ซ่งึ เปน copy ของ red (c.chanceRadius() มีคา
เทา กับการเรียกใช red.chanceRadius() น่นั เอง)
สง่ิ ที่เราตองจําไวในเร่ืองของการสง คา ใหกับ method กค็ ือ การสง คา ท่เี ปน primitive type เชน int
หรือ double นนั้ method จะไดร บั แตเพยี งคา เทานั้น การเปลยี่ นแปลงใด ๆ ภายใน method จะไมมี
ผลกระทบตอตัวแปรดา นนอก แตถ า เราสง object ไปให method การเปล่ยี นแปลงทเี่ กดิ ขน้ึ ภายใน
method (ตอ filed นัน้ ๆ ของ object) จะมีผลกระทบตอ object ทอี่ ยภู ายนอกดวย เพอื่ ใหเห็นภาพ
ชดั เจนย่งิ ขึ้นเราจะมาดูตัวอยา งการสง คาอา งอิงอีกสกั ตัวอยางหนึ่ง
1: /**
2: Passing reference
3: */
4:
5: class Being {
6: public String name = "no_name";
7:
8: public Being(String name) {
9: this.name = name;
10: }
11:
12: public String toString() {
13: return "[" + name + "]";
14: }
15: }
16:
17: class PassingRef {
18: public static void main(String[] args) {
19: Being something = new Being("Joe");
20:
21: System.out.println("Being's before: " + something);
22: morphed(something);
23: System.out.println("Being's after: " + something);
24: }
25:
26: private static void morphed(Being ref) {
27: ref.name = "Jack";
28: }
29: }
ผลลพั ธที่เราไดค ือ
Being's before: [Joe]
Being's after: [Jack]
ในโปรแกรมตัวอยา งของเรา เราประกาศให something เปน object จาก class Being พรอมทง้ั
กําหนดใหค า ของ field ที่ช่ือ name มคี า เปน "Joe" ภายใน class Being เรายงั ไดก ําหนดใหมี
method ชอ่ื morphed() ท่ีทําหนา ทีใ่ นการเปลยี่ นคา filed: name ใหเปนไปตามสง่ิ ที่สง เขา มา ซงึ่
เราก็ไดก ําหนดใหค า ใหมเ ปน "Jack" ผอู านจะเหน็ วาผลลพั ธท่ีเราไดจากการ run โปรแกรมเปน ไป
ตามท่ีเราคาดไว คอื คา ของ name ถูกเปลี่ยนเปน "Jack" (เพราะวา morphed() กระทาํ กับ field
ของ object ไมใช object โดยตรง) ผูอานจะสังเกตเห็นวา morphed() เรียกใช filed: name ผา น
ทางตวั แปร ref ไดโดยตรงทงั้ นก้ี เ็ พราะวาเราไดก ําหนดให filed น้ีมกี ารเขาหาแบบ public แตถา เรา
กาํ หนดใหเ ปน private เหมือนกบั radius ในตัวอยา งกอ นหนา นเ้ี ราก็ไมสามารถเขา หาไดโดยตรง
ตองเขาหาผานทาง method ทอ่ี ยภู ายใน class นัน้ เทา น้นั (ผานทาง changeRadius())
[การสลบั คา ของสิ่งสองส่ิง]
สมมติวา เราตองการที่จะทําการสลบั คา ของตวั แปรสองตัว ผา นทาง method เราจะทาํ อยา งไร? เรา
มาลองดตู วั อยา งแรกกันกอนวาจะทําใหเราไดหรอื ไม โดยทวั่ ไปในการเขียน code เพ่อื สลับคาของ
ตัวแปรสองตวั นั้น เราตอ งมตี ัวแปรตัวทส่ี ามเปน ทีพ่ กั คาทตี่ องการสลบั เชน ถาเรามีตัวแปรสองตัว
173
เรมิ่ ตนการเขยี นโปรแกรมดวย Java intro. to Java (FEU.faa)
num 1 และ num 2 (ซง่ึ มีคาอยแู ลว ) เราตองกําหนดตวั แปรอีกหนึ่งตวั เพือ่ พกั คา สมมตวิ าเรามี
temp เปนทพี่ ักคา สง่ิ ทีเราตอ งทาํ ก็คอื
1: /**
2: Exchange values of two objects
3: */
4:
5: import static java.lang.System.out;
6:
7: //Simple class to store values
8: class Values {
9: int val1;
10: int val2;
11:
12: //default constructor
13: Values() {
14: val1 = val2 = 0;
15: }
16:
17: //assignment constructor
18: Values(int a, int b) {
19: val1 = a;
20: val2 = b;
21: }
22:
23: //display val1 & val2
24: public void show() {
25: out.println("(" + val1 + ", " + val2 + ")");
26: }
27: }
28:
29: class Swap {
30: public static void main(String[] args) {
31: //create two objects from Values
32: Values obj1 = new Values(10, 20);
33: Values obj2 = new Values(30, 50);
34:
35: obj1.show(); //display values of obj1
36: obj2.show(); //display values of obj2
37:
38: swap(obj1, obj2); //swap contents of obj1 and obj2
39:
40: obj1.show();
41: obj2.show();
42: }
43:
44: //swapping contents of given objects
45: private static void swap(Values pointA, Values pointB) {
46: Values temp = new Values();
47:
48: temp = pointA; //copy pointA to temp
49: pointA = pointB; //copy pointB to pointA
50: pointB = temp; //copy temp to pointB
51: }
52: }
เรากาํ หนดใหก ารสลบั คาของ object ทง้ั สองเกิดขึน้ ภายใน swap() ซงึ่ เราคดิ วานา จะทาํ ได 100%
แตหลังจากท่ี run โปรแกรมดู เรากลบั ไดผลลัพธด งั น้ี
(10, 20)
(30, 50)
(10, 20)
(30, 50)
ซง่ึ บอกใหเรารูวา swap() ของเราใชไ มไ ด ดังนน้ั เราจึงตองหาวธิ กี ารใหมท ่ที ําใหการสลบั คาน้นั เกดิ
จริง ลองดู code ทเี่ ขยี นขึน้ ใหมน ้ี
private static void swap(Values pointA, Values pointB) {
Values temp = new Values();
temp.val1 = pointA.val1;
174
บทที่ 5: Objects และ Classes intro. to Java (FEU.faa)
temp.val2 = pointA.val2;
pointA.val1 = pointB.val1;
pointA.val2 = pointB.val2;
pointB.val1 = temp.val1;
pointB.val2 = temp.val2;
}
ผลลพั ธท ีเ่ ราไดคือ
(10, 20)
(30, 50)
(30, 50)
(10, 20)
ซึ่งแสดงถงึ การสลับคา ท่ีไดผ ลจรงิ สาเหตุที่ swap() ตวั แรกของเราทาํ งานไมได ก็เน่อื งจากวา การ
เปลยี่ นแปลงคา ของ object เกิดขึ้นจาก copy ของ object ทงั้ สองท่ีมาจาก parameter ไมใ ช filed
ของ object จริง ๆ ดังน้นั การเปลยี่ นแปลงทเ่ี กิดขึ้นจึงเกิดข้ึนภายในตวั swap() ไมม ีผลกระทบใด ๆ
กับ object ภายนอกเลย เราตองทําการเปลีย่ นคา ใหกบั สมาชกิ ทอ่ี ยูใน object นนั้ โดยตรงดงั เชน ท่ี
swap() ตวั ทีส่ องไดแสดงไว
สิง่ ทีเ่ ราตองจําไวเสมอก็คอื java ไมมี address operator1 ทีเ่ ราสามารถใชใ นการสง ทอ่ี ยูใหกับ
method เหมอื นภาษาอื่นๆ เชน C หรอื C++ ทกุ ๆ ครั้งที่มกี ารสง ตวั แปร หรือ object ไปให method
เปน การสงคา ทั้งส้ิน ดังนน้ั เราจงึ ไมส ามารถท่ีจะเขียน method สาํ หรบั การเปลย่ี นคา ใหก บั primitive
data type ผานทาง parameter list ได
เราไดพ ดู ถึง class Student ที่เราสรางคางไวโ ดยเราไดส ํารวจ การสราง method ตาง ๆ รวมไปถึง
การสง คา เขา สู method ตอนนเี้ ราจะมาดูถงึ รายละเอยี ดของ method ตา ง ๆ ที่มอี ยใู น class
Student รวมไปถึงโปรแกรมทีเ่ รยี กใช object ท่เี กิดจาก class Student
กอ นที่เราจะพูดถึง method ทมี่ อี ยใู น class Student เรามาดูตวั โปรแกรมทเี่ รียกใช method เหลา นี้
ดู
1: /**
2: Testing module for class Student
3: */
4:
5: import static java.lang.System.out;
6:
7: class TestStudent {
8: public static void main(String[] args) {
9: //create two student objects with given info.
10: Student stu1 = new Student("19757", "Jim", "Jones", "02/10/1962");
11: Student stu2 = new Student("20135", "Ray", "Smith", "12/09/1977");
12:
13: //display each student's info.
14: stu1.display();
15: stu2.display();
16:
17: //display total number of students
18: out.printf("Total number of objects created: %d%n", stu1.getCount());
19:
20: //access field in class via object
21: String date = stu1.dateOfBirth;
22: out.printf("Date of birth of stu1 is %s%n", date);
1 Address operator ใน C++ เชน &number หมายถึงตาํ แหนง ที่อยขู องตัวแปร number ในหนวยความจาํ และถา เราจะ
เขยี น swap() สําหรบั การสลบั คาของตวั แปรสองตวั เรากอ็ าจเขยี นไดดงั นี้
void swap(int &x, int &y) {
int temp = x;
x = y;
y = temp;
}
โปรแกรมเมอรห ลาย ๆ คนเสียดายการสง คา แบบนี้ หลังจากท่หี ันมาใช Java (แต Java กม็ สี งิ่ อาํ นวยความสะดวกอยา งอ่นื )
175
เรม่ิ ตนการเขยี นโปรแกรมดว ย Java
23: }
24: }
เราไดส รา ง object stu1 และ stu2 จาก class Student ดวยขอ มูลดังที่เหน็ intro. to Java (FEU.faa)
Student stu1 = new Student("19757", "Jim", "Jones", "02/10/1962")
Student stu2 = new Student("20135", "Ray", "Smith", "12/09/1977")
หลงั จากนั้นเรากเ็ รยี กใช method display() ในการแสดงผลขอมูลของ object ทัง้ สองตัว โดยทีเ่ รา
ไดออกแบบ method display() ของเราใหมีการเรียกใช method อ่นื ๆ ท่ีมอี ยูใน class Student
ดงั น้ี
public void display() {
out.printf("%s %s %s", getId(), getFirstName(), getLastName());
out.printf(" [Age: %s]%n", getAge());
}
ผูอ า นจะสงั เกตไดวา เราเรียก method getId() getFirstName() getLastName() และ method
getAge() ภายในประโยคของ out.printf(…) ซ่งึ method เหลานจ้ี ะสงคาของ field ตาง ๆ ท่ีไดถกู
กําหนดไวใ หก บั ประโยคในการแสดงขอ มลู ไปยังหนา จอ
หลังจากท่ีขอ มูลของ object ทงั้ สองตวั ไดถ กู แสดงไปยงั หนา จอแลว เราก็เรยี กประโยค
out.printf("Total number of objects created: %d%n", stu1.getCount());
String date = stu1.dateOfBirth;
out.printf("%s's birthdate is %s%n", stu1.getFirstName(), date);
สําหรับการแสดงจํานวนของ object ทไ่ี ดถกู สรา งข้นึ ท้งั หมด และวัน เดือน ป เกิดของ object ทช่ี ื่อ
stu1 ไปยงั หนา จอ และผลลัพธของการ run ทีไ่ ดคือ
19757 Jim Jones [Age: (15801 days) 43 years 3 months 5 days]
20135 Ray Smith [Age: (10342 days) 28 years 3 months 25 days]
Total number of objects created: 2
Jim's birthdate is 02/10/1962
ผูอ านตองกาํ หนดใหก ารเรียก method ท่ีมีอยูใน class ผานทาง object ท่ีไดส รา งขนึ้ ดว ยการใช .
(dot) ตามดวยช่ือของ method ท่ีตอ งการเรยี กใช เชน
stu1.display();
เชน เดียวกนั กบั การเรยี กใช data member เราก็ตอ งขนึ้ ตน ดว ยชื่อของ object ตามดวย . (dot) ตาม
ดว ย ตวั แปรทต่ี อ งการใช เชน
stu1.dateOfBirth;
เนอื่ งจากวาเราไมไดก ําหนดนโยบายการเขา หา ตัวแปร หรอื method ทม่ี ีอยูใ น class ดังนั้นการเขา
หาจงึ ไมข อ กาํ หนดใด ๆ เราสามารถท่ีจะเขาหาขอมลู ทกุ ตวั โดยไมมขี อจาํ กดั กอ นทีเ่ ราจะพูดถงึ
นโยบายการเขา หาขอมลู ทอี่ ยใู น class เราอยากทีจ่ ะพดู ถึง method getAge() ท่มี อี ยูใ น class
Student สักเล็กนอ ย
method getAge() ไดถูกออกแบบใหท าํ การคาํ นวณหาอายจุ ากการเปลยี่ นเวลาจากวันเกิดใหมคี า
เปน millisecond แลวจงึ หาคา แตกตา งระหวา งเวลาเกิดกับเวลาปจจบุ นั ในเครอื่ ง (ตอน execute
โปรแกรม) เมือ่ ไดก ็ทาํ การเปลี่ยนใหเ ปน วัน เดือน และป กระบวนการในการคาํ นวณหาอายทุ ี่เรา
เขยี นข้ึน ไมใ ชกระบวนการท่ีละเอยี ด หากเปนแคการคาํ นวณท่ีใหคา ไดใ กลเ คยี งความเปนจริง
พอสมควร เราตงั้ สมมติฐานวา ผใู ชต อ งใสว นั เดือน ปเ กดิ ในรปู ของ วนั /เดือน/ป และปฏทิ นิ ของเคร่ือง
(locale) ถูกตัง้ ใหเปน คา ของประเทศสหรัฐอเมรกิ า
Locale.setDefault(new Locale("en_US"));
ADJUST_TIME = 1970;
176
บทที่ 5: Objects และ Classes intro. to Java (FEU.faa)
เราตอ งกําหนดใหมีคา การปรับเวลาของตวั ปฏทิ ินใหเปน 1970 ทั้งน้ีก็เนือ่ งจากวาไดถูกกําหนดมา
จาก Java เองวาการเร่มิ ตน นับเวลาของ Java นั้นเรม่ิ ตน ที่ เดอื นมกราคม ป 1970 ที่ 00.00.00.000
GMT
เราจะคาํ นวณหาเวลาเกิดและเวลาของเคร่ือง ณ เวลาท่ี run โปรแกรมเปน millisecond ซ่งึ เม่ือหัก
ลบออกจากกันก็จะไดเ วลาทีเ่ ปน อายทุ ่ตี อ งการหา การคํานวณหาอายุเปน วนั ก็ทาํ ไดด ว ยการหารคา ท่ี
ไดดวย (1000*60*60*24) และคํานวณหาจํานวน ป เดือน และวนั จากการเรียกใช method ของ
class Calendar
long elapsedTime = Math.abs(dob - System.currentTimeMillis());
cal.setTimeInMillis(elapsedTime);
long ageInDays = elapsedTime / (1000*60*60*24);
int years = cal.get(Calendar.YEAR) - ADJUST_TIME;
int months = cal.get(Calendar.MONTH);
int days = cal.get(Calendar.DAY_OF_MONTH) - 1;
Java ยงั มี class GregorianCalendar ทเ่ี ราสามารถเรียกใชใหแ สดงขอมูลเกยี่ วกับปฏทิ ิน หรอื ใช
คํานวณหาเวลาตาง ๆ เชน ระยะเวลาท่ีพนักงานทํางานกบั บริษทั (จากวนั ทจ่ี า งงาน เปน ตน ) ตวั อยาง
โปรแกรมตอไปน้ีเปน โปรแกรมตัวอยา งการแสดงปฏิทนิ จากปแ ละเดือนท่กี ําหนดใหจากผใู ช โดย
เรยี กใช class GregorianCalendar เปน class หลักในการคํานวณ ซึ่งเมอ่ื run แลว ผลลพั ธทไ่ี ดจ ะ
อยใู นรปู แบบคลา ย ๆ กบั ที่เหน็ น้ี
1: /**
2: printing calendar from a given year and month
3: e.g. 2006 and 1 (January 2006)
4: */
5:
6: import static java.lang.System.out;
7: import java.lang.StringBuffer;
8: import java.util.Scanner;
9: import java.util.GregorianCalendar;
10: import java.util.Locale;
11: import java.text.DateFormatSymbols;
12: import static java.util.Calendar.*;
13: import javax.swing.JOptionPane;
14: import javax.swing.JTextArea;
15: import java.awt.Font;
16:
17: class CalendarPrinting {
18: public static void main(String[] args) {
19: String input = "";
20: input = JOptionPane.showInputDialog(null,
21: "Enter YEAR and MONTH (separate by space)",
22: "Calendar",
23: JOptionPane.QUESTION_MESSAGE);
24:
25: Scanner in = new Scanner(input);
26: int year = in.nextInt();
27: int month = in.nextInt() - 1;
28:
29: //exit if month is not between January (0) and December (11)
30: if(month < 0 || month > 11) {
31: JOptionPane.showMessageDialog(null,
32: "Not a valid month,\nUse value between 1 and 12",
33: "Error",
34: JOptionPane.ERROR_MESSAGE);
177
เริม่ ตนการเขยี นโปรแกรมดวย Java intro. to Java (FEU.faa)
35: System.exit(1);
36: }
37:
38: //set this machine's locale to US
39: Locale.setDefault(new Locale("en_US"));
40: DateFormatSymbols df = new DateFormatSymbols();
41:
42: //get name of month (e.g. January)
43: String[] months = df.getMonths();
44: String mName = months[month];
45:
46: //get name of week (e.g. Sun)
47: String[] weeks = df.getShortWeekdays();
48: String week = "";
49: for(String w : weeks)
50: week += String.format("%s ", w);
51:
52: //create calendar with given year and month
53: GregorianCalendar c = new GregorianCalendar(year, month, 1);
54: //set c to start date of the month
55: c.set(DAY_OF_MONTH, 1);
56: StringBuffer buf = new StringBuffer();
57:
58: /**
59: calculate position of month name
60: then print it above the week
61: */
62: int length = week.length();
63: int dif = length - mName.length();
64: for(int i = 0; i < dif / 2; i++)
65: buf.append(String.format("%c", ' '));
66: buf.append(mName + "\n" + week + "\n");
67:
68: //indent first week
69: int weekday = c.get(DAY_OF_WEEK);
70: int firstDayOfWeek = c.getFirstDayOfWeek();
71: for(int i = firstDayOfWeek; i < weekday; i++)
72: buf.append(String.format("%4c", ' '));
73:
74: /**
75: print days in month
76: repeat till next month is encountered
77: */
78: do {
79: int day = c.get(DAY_OF_MONTH);
80: buf.append(String.format("%4d", day));
81: //start a new line
82: if(weekday == SATURDAY)
83: buf.append("\n");
84: //advance to next day
85: c.add(DAY_OF_MONTH, 1);
86: //get day of the week
87: weekday = c.get(DAY_OF_WEEK);
88: }
89: while(c.get(MONTH) == month);
90:
91: //display result
92: JTextArea result = new JTextArea();
93: result.setFont(new Font("Lucida Sans Typewriter", Font.PLAIN, 10));
94: result.append(new String(buf));
95: JOptionPane.showMessageDialog(null, result,
96: "Calendar " + year,
97: JOptionPane.INFORMATION_MESSAGE);
98: System.exit(0);
99: }
100: }
โปรแกรมของเราอานขอมูลสองตวั จากผใู ชคอื year และ month หลังจากทเ่ี ราไดกําหนดให locale
ของเครื่องใหเ ปน ภาษาอังกฤษของประเทศสหรฐั อเมริกาดวยคําสั่ง
Locale.setDefault(new Locale("en_US"));
178
บทท่ี 5: Objects และ Classes intro. to Java (FEU.faa)
เครอื่ งของเราก็จะใช locale ของประเทศสหรัฐอเมรกิ า (เน่อื งจากวา เครอ่ื งของผเู ขียนใช locale ของ
ประเทศไทย) โปรแกรมจะดึงเอาช่อื ของเดอื นและชื่อของวันจาก class DateFormatSymbols ดวย
การเรยี กใช
DateFormatSymbols df = new DateFormatSymbols();
String[] months = df.getMonths();
String mName = months[month];
String[] weeks = df.getShortWeekdays();
String week = "";
for(String w : weeks)
week += String.format("%s ", w);
method getMonths() จะใหคา ของเดือนแตละเดอื นในรูปแบบของ array of Strings ดังนน้ั เราก็
เพยี งแตด งึ เอาเดือนที่เราตองการใชจาก array ดงั กลาว สว นชอื่ ของวนั เราตองการใหอ ยใู นรปู ของ
ช่ือยอ ดังนั้นเราจึงเรียกใช getShortWeekdays() ซ่งึ อยูในรปู ของ array of Strings เชนเดยี วกนั
เพราะฉะน้ันเราจึงดงึ ทัง้ หมดมาเก็บไวในตัวแปร week
เราสรา งปฏิทนิ จาก class GregorianCalendar ดว ยคาํ ส่งั
GregorianCalendar c = new GregorianCalendar(year, month, 1);
c.set(DAY_OF_MONTH, 1);
โดยเราจะกาํ หนดใหป ฏทิ ินของเราเรมิ่ ตน ที่วนั ทห่ี น่งึ ของเดอื นจากการใช c.set(DAY_OF_MONTH,
1) และเม่ือเราไดก ําหนดหวั ตารางของปฏทิ ินดวยชื่อของเดือน และวนั แลว (ดู code บรรทดั ที่ 62 ถึง
66) เราตอ งแสดงวนั แรกของเดอื นใหถูกตองดว ยการกําหนดจาก
int weekday = c.get(DAY_OF_WEEK);
int firstDayOfWeek = c.getFirstDayOfWeek();
for(int i = firstDayOfWeek; i < weekday; i++)
buf.append(String.format("%4c", ' '));
คาของ weekday จะอยูระหวาง 1 ถึง 7 (วนั อาทิตย ถงึ วนั เสาร) และคาของ firstDayofWeek จะมี
คา เปน 1 (วนั อาทติ ย ซงึ่ จะข้นึ อยกู บั locale ที่กําหนดไว) เราจะเวนชองวางท่อี ยดู า นหนา ของ
weekday เพอื่ ใหแ สดงคาไดถ กู ตอ งตามวัน หลังจากนนั้ เราก็แสดงวันที่มีอยใู นเดอื นน้ีดวยคาํ สง่ั
do {
int day = c.get(DAY_OF_MONTH);
buf.append(String.format("%4d", day));
if(weekday == SATURDAY)
buf.append("\n");
c.add(DAY_OF_MONTH, 1);
weekday = c.get(DAY_OF_WEEK);
}
while(c.get(MONTH) == month);
เราเริ่มดว ยการหาวนั แรกของเดือนจาก day = c.get(DAY_OF_MONTH) และถา คา ของ weekday
ทเี่ ราหาไดก อ นหนา นี้มีคาเปน วนั เสาร (SATURDAY) เรากข็ ้ึนบรรทดั ใหม หลังจากนน้ั เราก็เล่ือนไปยงั
วันถดั ไปดว ย c.add(DAY_OF_MONTH, 1) และหาคาของ weekday ของวันใหมนี้ เราจะวน loop
ไปจนกวาเราจะไดวันทัง้ หมดทม่ี อี ยใู นเดอื นน้ี และเม่อื เรา run ดว ยป 2006 และเดอื นเมษายน
ผลลพั ธท ่เี ราไดค อื
179
เร่ิมตนการเขียนโปรแกรมดว ย Java intro. to Java (FEU.faa)
การใชก ารคาํ นวณแบบน้ีทําใหเ ราไมต อ งตรวจสอบปอธกิ สุรทนิ (leap year) และไมต องเขยี น code
ในการคาํ นวณหาช่อื เดอื นและช่อื วันใหย งุ ยาก เราเพียงแตเรียกใช method ของ class ท่ี Java มีไว
ใหกพ็ อ
ผูอา นอาจสงสัยวาคา ที่เปน อักษรตัวใหญมาจากไหน ทาํ ไมถงึ ไมมีการประกาศ คําตอบก็คอื เราไดทาํ
การ import คาตา ง ๆ เหลา น้ผี า นทาง static import เรยี บรอยแลว (บรรทดั ที่ 12) ซ่งึ ทจ่ี ริงแลวการ
เรยี กใชคาเหลา น้ถี าไม import แบบ static แลวเราตองมคี าํ วา Calendar นาํ หนา เชน
Calendar.DAY_OF_MONTH เปน ตน
การสราง class Student ของเราน้ันเราไมไ ดกาํ หนดนโยบายการเขา หา field หรือ method ตา ง ๆ
ของเราอยา งไรเลย ผูอา นคงสงั เกตเหน็ วา ตัวแปรทุกตัวของเราไมม ีคาํ ใด ๆ นาํ หนาเลย เชน private
public หรอื แมก ระทัง่ คาํ วา protected หัวขอ ตอ ไปจะพดู ถงึ เร่ืองของการกําหนดนโยบายการเขา หา
ตัวแปร และ method ของ class วาจะมีประโยชนอยา งไรในการออกแบบ class (ผูอา นลองตั้ง
คําถามใหต วั เองกอ นเร่ิมหัวขอถดั ไปวา ถา ใสค ําวา private หนา ตวั แปรทุกตัวจะมผี ลตอ โปรแกรม
TestStudent.java อยา งไร ถา ใสหนา method ตา ง ๆ หละ?)
5.3 การเขา หา field ของ class (attributes หรือ access modifier)
จาก class Circle ของเราที่ไดสรา งขน้ึ ในการประกาศตัวแปร radius น้ันเราไดกําหนดใหม คี ําวา
private อยดู านหนาของตวั แปร ดังนี้
private double radius;
ทําไมเราถงึ ทาํ เชนนี้?
สาเหตทุ ่ีเราทาํ เชนน้ีก็เพ่ือท่ีจะกําหนดการเขา หาตัวแปรตัวนี้ โดยท่ัวไปแลว ถาเราไมใสค ําวา private
ไวหนา ตวั แปรใด เราก็สามารถท่จี ะเขา หาตวั แปรตัวนี้ ผานทางโปรแกรมอนื่ ๆ ทีเ่ รยี กใช class Circle
การกาํ หนดนโยบายของการเขา หานน้ั เราสามารถทาํ ไดส่ีวิธี คือ
1. ไมใ ชค าํ ใด ๆ นําหนา ตัวแปร (friendly)
2. ใชค ําวา private นาํ หนาตวั แปร (not too friendly)
3. ใชค ําวา public นาํ หนาตัวแปร (friendly)
4. ใชค ําวา protected นาํ หนาตวั แปร (somewhat friendly)
ถาเราไมใ ชคาํ ใด ๆ นําหนาตวั แปรการเขาหาตัวแปรตัวนจ้ี ะทาํ ไดเ ฉพาะ class ทอ่ี ยูภายในพ้นื ที่
เดยี วกนั เชนภายใน class เดยี วกนั หรือภายใน package (ดูเรอื่ งการสรา งและใช package ทา ยบท)
เดียวกัน ดังโปรแกรมตวั อยา งทแี่ สดงใหดนู ้ี
1: /**
2: Demonstrate the use of access keyword
3: */
4:
5: //simple class with no restriction on fields
6: class Dot {
7: String name;
8: int value;
9:
180
บทที่ 5: Objects และ Classes intro. to Java (FEU.faa)
10: Dot(String s, int v) {
11: name = s;
12: value = v;
13: }
14: }
15:
16: class Access {
17: public static void main(String[] args) {
18: //create object: myDot from class Dot with
19: //String: "I am a dot." and an int: 10
20: Dot myDot = new Dot("I am a dot.", 10);
21:
22: //access both name and value fields from class Dot
23: System.out.println("Name is " + myDot.name);
24: System.out.println("Value is " + myDot.value);
25: }
26: }
เมื่อเรา run ดผู ลลัพธท ี่ไดคือ
Name is I am a dot.
Value is 10
โปรแกรม Access.java สามารถที่จะเขา หา field ท้ังสองท่ีเราสรา งขน้ึ ใน class Dot ของเราผา นทาง
object ชอื่ myDot (หมายความวาใคร ๆ กเ็ ขาหาตัวแปรของเราไดถ าเขารวู าเรามีตวั แปรอะไรบาง –
อนั ตราย?)
ทีนเี้ ราลองนําเอาคาํ วา private ไปใสไวห นาตวั แปรทงั้ สองของเรา ดงั น้ี
private String name;
private int value;
การ compile โปรแกรมอีกครง้ั หนึง่ จะทาํ ใหเกิด error ดงั น้ี
Access.java:23: name has private access in Dot
System.out.println("Name is " + myDot.name);
^
Access.java:24: value has private access in Dot
System.out.println("Value is " + myDot.value);
^
2 errors
เราไมสามารถที่จะอา งถึงตัวแปรทง้ั สองไดเพราะคาํ วา private เราตองเขาหาดว ยวิธอี ืน่ เชน เขยี น
method ทสี่ ง คาของตัวแปรท้ังสองกลบั (โดยเขียนไวใ น class Dot) เหมอื นกบั ทเ่ี ราไดทําไวใน
class Circle คอื
เรากําหนดใหต ัวแปร radius ของ class Circle เปน private data member ดงั นน้ั เราจงึ ตองเขยี น
method ในการเขา หาตัวแปร radius ของเราผา นทาง method ท่ไี ดประกาศใหเปน public ดงั นี้
public double getRadius() {
return radius;
}
เพราะฉะนัน้ ถา เราไมตองการใหโ ปรแกรม หรือ ผใู ด (object) เขา หาตัวแปรของเรา เรากน็ ําคาํ วา
private ไปใสไวด านหนา ของตวั แปรน้นั ๆ ถา สังเกตใหดีจะเห็นวา method changeRadius() ใน
class Circle ก็มีคําวา private อยูดานหนาเหมือนกัน ทง้ั นี้กเ็ พราะวา เราไมต องการใหใครเขาหา
method ตวั น้ียกเวน method ทอ่ี ยภู ายใน class เดยี วกนั การเขาหา method นผี้ านโปรแกรม หรือ
object ตวั อื่นจะทาํ ไมไ ด และ Java compiler จะฟอ งใหร บั ทราบทันที
เราจะกลบั มาดูคาํ วา protected ในโอกาสตอไป ทั้งนเี้ พราะคาํ ๆ นมี้ ีเงือ่ นไขซบั ซอ นอยพู อสมควร
สาํ หรบั คําวา public นน้ั จะยอมใหท ุกโปรแกรม หรอื object เขาหาตัวแปร หรือ method ไดโดยไมมี
เงื่อนไขใด ๆ ทั้งสน้ิ
181
เรม่ิ ตน การเขียนโปรแกรมดว ย Java intro. to Java (FEU.faa)
การกาํ หนดนโยบายการเขาหาตวั แปรหรอื method ทําใหก ารควบคุมโปรแกรมทาํ ไดด ยี ่ิงข้ึน อะไรท่ี
ผใู ชไมค วรรูไมควรเหน็ เราก็ซอ นสิ่งเหลานไ้ี ว การกระทําในลักษณะนีเ้ ราเรียกวา encapsulation ซ่ึง
เปนหนึ่งในขอกาํ หนดของการออกแบบและเขยี นโปรแกรมในรูปแบบของ OOP ในสว นตัวของผูเขยี น
แลว ชอบทีจ่ ะใช private กับตวั แปรทกุ ตวั และ method บางตวั ทีไ่ มม ีการเขาหาจากภายนอก เพราะ
จะทําใหการใชตัวแปรมีขอ จํากดั สว นที่เขา หาขอ มูลเหลานข้ี องเราไดเ ปน ไดเ ฉพาะ method ทเ่ี ราได
กําหนดไวเ ทานนั้
[finalize method]
finalize method เปน method ทถ่ี กู เรียกจาก garbage collector ของ Java เพ่อื ทีจ่ ะทาํ การคืน
หนวยความจาํ ท่ีโปรแกรมใชใหก บั ระบบ ซงึ่ โดยปกตแิ ลวจะถูกเรยี กโดยอัตโนมัติ ดังนนั้ เราจึงไม
จาํ เปนที่จะตอ งเขยี น method finalize() เพือ่ ทาํ การใด ๆ code ท่ีเห็นนี้เปนเพียงตัวอยางทแี่ สดงถึง
การเรยี กใชด ังกลาว
public void finalize() throws java.lang.Throwable {
out.printf("%s %s has been disposed.%n", firstName, lastName);
}
สมมติวาเราสราง method finalize() ดังกลาวใน class Student ท่ีเราไดเขียนขน้ึ กอ นหนา น้ี เพ่อื
แสดงขอมูลที่ถกู กาํ จัดออกจากระบบการทํางาน และเมอื่ เราเพ่มิ code ในโปรแกรม
TestStudent.java ดว ย
...
Student stu3 = new Student("11111", "Keith", "Wallace", "11/01/1958");
Student stu4 = new Student("22222", "Danny", "Daveto", "09/12/1960");
...
stu3.display();
stu4.display();
...
stu3 = stu4 = null;
System.gc();
ผลลัพธที่เราไดค ือ
19757 Jim Jones [Age: (15805 days) 43 years 3 months 9 days]
20135 Ray Smith [Age: (10346 days) 28 years 3 months 29 days]
11111 Keith Wallace [Age: (17530 days) 47 years 11 months 29 days]
22222 Danny Daveto [Age: (16467 days) 45 years 1 months 0 days]
Total number of objects created: 4
Jim's birthdate is 02/10/1962
Danny Daveto has been disposed.
Keith Wallace has been disposed.
ผูอานจะเหน็ วาเม่ือเรากาํ หนดให stu3 และ stu4 เปน null พรอมกับเรียกใช System.gc() ซึง่ เปน
การบอกให garbage collector ทํางาน เรากจ็ ะไดผ ลลัพธใ นสองบรรทดั สดุ ทา ยทเี่ ห็นดงั กลา ว และ
เมื่อโปรแกรมสิ้นสดุ การทาํ งานคาของ stu1 และ stu2 ก็จะเปน null ทาํ ให finalize() ถูกเรียกแต
เน่อื งจากวาโปรแกรมไดยุติการทํางานแลว ดงั นนั้ เราจึงไมเหน็ ขอ มูลใด ๆ บนหนา จอ
5.4 Constructor อีกครงั้
Constructor มีไวส าํ หรับการกําหนดคา เบื้องตน (initialization) ใหก บั ตัวแปรท่อี ยใู น class และการ
เรียกใช constructor นนั้ เราไมต องทาํ โดยตรง constructor จะถกู เรยี กโดยอตั โนมัติผานทางการ
สราง object จาก class ดังทีไ่ ดแ สดงไวใ นโปแกรมที่สราง object จาก class Circle จากประโยค
ของการสรางวงกลมที่วา
Circle red = new Circle(5.0);
ข้ันตอนทเ่ี กดิ ขนึ้ เมือ่ ประโยคนีถ้ กู execute คือ
182
บทท่ี 5: Objects และ Classes intro. to Java (FEU.faa)
Constructor ของ Circle ถูกเรียกดว ยคา 5.0 ซ่งึ หมายความวา ตวั แปร radius ท่อี ยูใน class Circle
จะไดรับคา ท่กี ําหนดให คอื 5.0 หลงั จากนน้ั ตําแหนง หรือ address ของ object ทถี่ กู สรางและ
กาํ หนดคา นี้จะถูกเกบ็ ไวใน red สว นประโยคที่ตามมา
out.println("Constructor activated with parameter value of " + radius);
ก็จะทาํ ใหเกดิ การแสดงผลไปยงั หนา จอดงั ทเ่ี ราไดเ ห็นจากผลลพั ธกอ นหนา น้คี อื
Constructor activated with value of 5.0
Constructor activated with value of 3.5
เราจะเห็นวา object สองตัวถกู สรา งดว ย radius ทีต่ า งกนั คอื 5.0 และ 3.5 และท้งั ๆ ทไี่ มมีประโยค
ของการแสดงผลใน method main() ใด ๆ เลย เรากลบั ไดผ ลลัพธดังทีเ่ หน็ ทั้งน้กี เ็ พราะวา
constructor ของเราทีม่ อี ยูใน class Circle ไดร ับการเรยี กใชโ ดยอัตโนมตั ิ กอนที่เราจะพดู ถงึ การ
overload constructor เราจะมาดกู นั ถงึ การกําหนดคา เบ้อื งตน ดวยการใชส งิ่ ที่ Java เรียกวา
initialization block
[Initialization blocks]
Initialization block เปนวธิ ีการอีกอนั หนงึ่ ท่เี ราสามารถนํามาใชในการกาํ หนดคาเบ้ืองตนใหกบั field
ตา ง ๆ ทม่ี อี ยูใน class ทเ่ี ราสรา งขึน้ initialization block เปนสวนของการกําหนดคาท่อี ยูใน class
โดยไมยุง เกี่ยวหรอื เปนสวนหน่งึ ขององคประกอบอื่น ๆ ของ class เชน constructor และจะถูกเรียก
โดยอัตโนมตั เิ ชนเดยี วกับ constructor แตผใู ชไมจาํ เปน ตองสรา ง object จาก class น้ี ลองดู
ตวั อยาง
1: /**
2: Initilization block
3: */
4:
5: class SimpleNameClass {
6: private long id;
7: private String name;
8: private static long nextId = 0;
9:
10: //initialization block
11: {
12: id = nextId++;
13: }
14:
15: SimpleNameClass(String name) {
16: this.name = name;
17: }
18:
19: public void print() {
20: System.out.printf("%3d:%s%n", id, name);
21: }
22: }
23:
24: class InitializationBlockDemo {
25: public static void main(String[] args) {
26: SimpleNameClass sn1 = new SimpleNameClass("Jon Doe");
27: SimpleNameClass sn2 = new SimpleNameClass("Jim Doe");
28:
29: sn1.print();
30: sn2.print();
31: }
32: }
จากโปรแกรมตัวอยา งเรากาํ หนดใหม ี Initialization block ในบรรทัดที่ 11 ถงึ 13 สําหรบั การ
ปรับปรงุ คา ของ class variable: nextId ท่เี ราประกาศไวใ นบรรทดั ท่ี 8 เมอ่ื เราทดลองสราง object 2
ตัวใน main() พรอมกบั เรียก print() ผลลพั ธทเี่ ราไดคือ
0:Jon Doe
1:Jim Doe
183
เริม่ ตน การเขยี นโปรแกรมดว ย Java intro. to Java (FEU.faa)
ผูอ า นจะเห็นวาเรามี constructor ทท่ี าํ การกาํ หนดคา ใหแก filed: name เทานั้นแตเ ราไดคา ของ id
ดว ยท้ังน้ีก็เนือ่ งมาจาก code ทีอ่ ยูในสว นของ initialization block น่นั เอง
[Static initialization block]
หลาย ๆ ครั้งท่เี ราตองการกําหนดคา เบอื้ งตนทซี่ บั ซอนกวาการกําหนดคาของตัวแปรโดยทัว่ ไป เชน
คาเบ้อื งตนของ array เรากอ็ าจหนั มาใชวธิ ีการกาํ หนดคา ดว ยการใช static initialization ซ่งึ ก็คลาย
ๆ กับการกําหนดคาใน initialization block เพียงแตวา เราตองทาํ กับตัวแปรทเ่ี ปน static เทา นัน้ เอง
ดงั ตวั อยา งตอ ไปนี้
1: /**
2: Static initialization block
3: */
4:
5: class SimpleCharArray {
6: private static char []chars = new char[26];
7:
8: static char ch = 'A';
9: static {
10: for(int i = 0; i < 26; i++, ch++)
11: chars[i] = ch;
12: }
13:
14: static {
15: System.out.print("[" + chars[0]);
16: for(int c = 1; c < 26; c++) {
17: System.out.print(", " + chars[c]);
18: }
19: System.out.println("]");
20: }
21:
22: SimpleCharArray() {}
23: }
24:
25: class StaticInitializationBlock {
26: public static void main(String[] args) {
27: SimpleCharArray characters = new SimpleCharArray();
28: }
29: }
โปรแกรมตวั อยางของเรากําหนดให chars เปน array ที่เก็บตวั อักษรภาษาอังกฤษตวั ใหญจ าก A ถึง
Z ในบรรทัดที่ 6 และเราไดก าํ หนดคา เบอื้ งตน ใหก ับ chars จาก static block ในบรรทัดที่ 9 ถึง 12
พรอมกนั น้ีเราก็ไดสรา ง static initialization block อกี ตวั หน่ึงเพอ่ื แสดงคา ใน chars ในบรรทดั ที่ 14
ถึง 20 ผลลัพธท ่เี ราไดจ ากการ run ก็เปนไปตามท่ีคาดหวังไวคือ
[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]
ถงึ แมว าเราสามารถทีจ่ ะใช constructor ทาํ หนา ทใ่ี นการกาํ หนดคา เบ้ืองตนใหกับ object ไดแ ต
บางคร้งั ในการเขียนโปรแกรม เราอาจตองการให constructor หลาย ๆ ตวั ทมี่ อี ยูมีสว นหนึ่งทีท่ ํา
หนาทใี่ นการกาํ หนดคา เบือ้ งตนท่เี หมือนกัน เพราะฉะนั้นการใช static initialization กท็ ําใหงานของ
เรางายขึน้
[Constructor overloading]
เราสามารถท่ีจะสราง constructor ใหกบั class ไดม ากกวา หน่ึงตัวทั้งนกี้ ารกระทําดังกลาวจะตองอยู
ภายใตเง่ือนไขท่ี Java กาํ หนดไว คือ parameter ที่สง ไปยงั constructor ตองไมมจี ํานวนทีเ่ ทา กนั
และ ถาจํานวนของ parameter เทา กนั ชนิดของ parameter ตองไมเหมือนกนั (หนังสอื เกอื บทุก
เลม เรยี กขั้นตอนนีว้ าการกาํ หนด signature) ลองดูโปรแกรมตัวอยาง
1: /**
2: simple class to demonstrate the use
3: of overloaded constructors
4: */
5:
6: import static java.lang.System.out;
184
บทที่ 5: Objects และ Classes intro. to Java (FEU.faa)
7:
8: class Mean {
9: private double x, y, z;
10:
11: //constructor with one value
12: Mean(double value) {
13: x = value;
14: y = 0.0;
15: z = 0.0;
16: }
17:
18: //constructor with two values
19: Mean(double value1, double value2) {
20: x = value1;
21: y = value2;
22: z = 0.0;
23: }
24:
25: //constructor with three values
26: Mean(double value1, double value2, double value3) {
27: x = value1;
28: y = value2;
29: z = value3;
30: }
31:
32: public double findMean() {
33: return (x + y + z) / 3;
34: }
35: }
36:
37: //test module for class Mean
38: class TestMean {
39: public static void main(String[] args) {
40: //create objects with diferent parameters
41: Mean m = new Mean(12.0);
42: Mean n = new Mean(10.0, 20.0);
43: Mean p = new Mean(10.0, 20.0, 30.0);
44:
45: //display averages of objects created
46: out.printf("Mean of m is %.2f%n", m.findMean());
47: out.printf("Mean of n is %.2f%n", n.findMean());
48: out.printf("Mean of p is %.2f%n", p.findMean());
49: }
50: }
Class Mean ของเรามี constructor อยูสามตวั โดยท่ีตวั แรกมี parameter หนึ่งตวั constructor ตวั
ที่สองมี parameter สองตัว และ constructor ตวั ทสี่ ามมี parameter สามตวั ภายใน class เราได
สราง method findMean() สําหรับการคาํ นวณหาคาเฉล่ียของตวั แปรทงั้ สามของ class และเราได
เขียนโปรแกรมสําหรับตรวจสอบการใช constructor ดงั กลา ว
โปรแกรม TestMean.java ประกาศใช object จาก class Mean สามตัวดว ยจาํ นวนของ parameter
ท่ีตางกนั คือ หนึง่ ตวั สองตัว และสามตัวตามลาํ ดับ หลงั จากทีเ่ ราเรยี ก method findMean() สําหรับ
object ทงั้ สามตวั แลว ผลลพั ธท ี่เราไดจ ากการ run คือ
Mean of m is 4.00
Mean of n is 10.00
Mean of p is 20.00
จะเห็นวา Java เลอื กใช constructor ไดถูกตอ งตามการออกแบบทเ่ี รากําหนดไว ซึ่งวิธีการแบบนี้เรา
เรียกวา การ overload สิง่ ทีเ่ กดิ ขึ้นก็คอื Java จะไปคนหา constructor ใน class Mean ท่มี เี งื่อนไข
ถกู ตองตามการประกาศ นนั่ กค็ ือ ภายใน class Mean เราจะตองมี constructor ท่มี ี parameter อยู
ครบทงั้ สามแบบ (1, 2, และ 3 parameter) Java กจ็ ะเลอื กใช constructor ท่ถี ูกตองตามการเรียก
และถา หากไมม ี constructor ดังกลาวก็จะฟอ งไปยังผใู ชทันที
เรามาลองดูการ overload ของ constructor ทีม่ ีจํานวนของ parameter เหมอื นกนั แตตา งชนิดกัน ดู
อีกสกั ตัวอยางหนง่ึ
1: /**
185
เรมิ่ ตนการเขยี นโปรแกรมดว ย Java intro. to Java (FEU.faa)
2: Constructor with different types as parameters
3: */
4:
5: import static java.lang.System.out;
6:
7: class Mean {
8: private double x, y, z;
9:
10: //constructor with three values
11: Mean(double value1, double value2, double value3) {
12: x = value1;
13: y = value2;
14: z = value3;
15: }
16:
17: //constructor with three values (different type)
18: Mean(double value1, int value2, String value3) {
19: x = value1;
20: y = (double)value2;
21: z = Double.parseDouble(value3);
22: }
23:
24: public double findMean() {
25: return (x + y + z) / 3;
26: }
27: }
28:
29: //test module
30: class TestMean1 {
31: public static void main(String[] args) {
32: //create objects with different parameters
33: Mean p = new Mean(10.0, 20.0, 30.0);
34: Mean q = new Mean(10.0, 20, "30.0");
35:
36: //display averages of objects created
37: out.printf("Mean of n is %.2f%n", p.findMean());
38: out.printf("Mean of p is %.2f%n", q.findMean());
39: }
40: }
Class Mean ของเรากําหนดใหม ี constructor สองตัว โดยกาํ หนดใหต ัวแรกรับ parameter ทีเ่ ปน
double ท้งั สามตัว สว น constructor ตัวที่สองรับ parameter ทเ่ี ปน double int และ String
ตามลําดับ ซงึ่ เราไดเปล่ยี นคา ทไ่ี มใ ช double ของท้ังสอง parameter ใหเปน double ภายในตวั
constructor เอง
โปรแกรม TestMean1.java ประกาศการใช object สองตัวคอื p และ q จาก class Mean ดวย
parameter ตา งกนั ดังท่เี ห็น ผลลพั ธท่ไี ดของการ run คือ
Mean of p is 20.00
Mean of q is 20.00
เชน เดยี วกับโปรแกรมกนอหนานี้ ผลลัพธท ่ีไดแ สดงถึงการเรียกใช constructor ทถี่ ูกตองของ Java
ยังมีวิธอี ่นื ทเ่ี ราสามารถทจี ะ overload constructor ได วธิ ีนีเ้ ราจะเรยี ก constructor ตัวอื่นจาก
constructor อกี ตวั
5.4.1 การเรยี ก constructor จาก constructor
วิธกี ารเรยี ก constructor จาก constructor ก็ไมย าก เราพียงแตก ําหนดวธิ กี ารเรียกใหเ หมาะสม ซ่งึ
Java ยอมใหม ีการเรียก constructor จาก constructor ผานทางคําวา this ดงั ตัวอยา งที่ไดแ สดง
ดงั น้ี
1: /**
2: Overloading constructor, calling constructor within constructor
3: */
4:
5: class Mean {
6: private double x, y, z;
186
บทท่ี 5: Objects และ Classes intro. to Java (FEU.faa)
7:
8: //constructor with one value
9: Mean(double value) {
10: x = value;
11: y = 0.0;
12: z = 0.0;
13: }
14:
15: //constructor with two values
16: Mean(double value1, double value2) {
17: //calling constructor with one argument
18: this(value1);
19: y = value2;
20: }
21:
22: //constructor with three values
23: Mean(double value1, double value2, double value3) {
24: //calling constructor with two arguments
25: this(value1, value2);
26: z = value3;
27: }
28:
29: public double findMean() {
30: return (x + y + z) / 3;
31: }
32: }
33:
34: //test module
35: class TestMean2 {
36: public static void main(String[] args) {
37: //create objects with diferent parameters
38: Mean m = new Mean(12.0);
39: Mean n = new Mean(10.0, 20.0);
40: Mean p = new Mean(10.0, 20.0, 30.0);
41:
42: //display averages of objects created
43: System.out.println("Mean of m is " + m.findMean());
44: System.out.println("Mean of n is " + n.findMean());
45: System.out.println("Mean of p is " + p.findMean());
46: }
47: }
เราไดด ดั แปลงโปรแกรมของการหาคา เฉลย่ี ของเลขสามตวั กอ นหนา นใ้ี ห มี constructor ที่เรยี กใช
constructor ดงั นี้
Mean(double value) {
x = value;
y = 0.0;
z = 0.0;
}
Mean(double value1, double value2) {
//calling constructor with one argument
this(value1);
y = value2;
}
Mean(double value1, double value2, double value3) {
//calling constructor with two arguments
this(value1, value2);
z = value3;
}
constructor ตวั แรกกาํ หนดคา ใหก ับตวั แปรเชนเดียวกบั ทไี่ ดท ําไวกอ นหนานี้ สว น constructor ตัวท่ี
สองและสามเรียกใช constructor ทม่ี ีอยูภ ายใน class Mean ดว ยการเรียกผาน this() โดยท่ี
constructor ตวั ท่สี องเรยี ก constructor ตัวแรกดว ยคาํ สง่ั this(value1) เม่อื Java เห็นการเรยี ก
เชน น้ี ก็จะไปหา constructor ท่ีมีอยใู น class วามีตัวไหนบางที่มีเงอื่ นไขตามท่ถี กู เรียก ซ่ึงกเ็ ปน ไป
ตามนนั้ คือ Java ไปเรยี ก constructor ทมี่ ี parameter เพียงตัวเดียวมาทําการกําหนดคา เบ้ืองตน
ใหก ับ object ที่ execute constructor ตัวน้ี คอื x จะมีคา เปน value1 y และ z จะมีคาเปน 0.0 จาก
187
เรม่ิ ตนการเขยี นโปรแกรมดว ย Java
การกําหนด หลงั จากน้ันการกาํ หนดคา ให y เปน value2 กไ็ ดถูกกระทาํ ภายใน constructor ตวั ที่ intro. to Java (FEU.faa)
สอง
constructor ตวั ท่สี ามก็เชน เดียวกนั การเรยี ก constructor ทีม่ ี parameter 2 ตัวก็เกดิ ข้นึ
กระบวนการเดิมทีไ่ ดก ลา วไวก อ นหนานก้ี ไ็ ดถูกกระทาํ ขึ้น เมือ่ ทาํ เสร็จแลว การกําหนดคาใหกบั ตัว
แปร z จึงมีขนึ้ (ผลลัพธของโปรแกรม TestMean2.java ก็เหมอื นกับทีเ่ ราไดก อนหนา นี้)
การเรยี กใช constructor ทม่ี ีอยแู ลว ทําใหก ารเขยี น code ที่ซาํ้ ซอ นลดลง การเขยี นโปรแกรมกม็ ี
ประสทิ ธิภาพมากขน้ึ
[this]
this เปน keyword ทเี่ ราสามารถเรยี กใชในการเจาะจง filed ทีอ่ ยใู น class นน้ั ๆ เมอื่ มกี ําหนดคา
ใหก บั filed ผานทาง method หรือ constructor เชน ที่เราไดท ํากับ field: name ของ class Being
ดังนี้
public Being(String name) {
this.name = name;
}
ในทีน่ ้ี this อางถงึ object ทไ่ี ดถ ูกสรางข้นึ และเปน object ทกี่ ําลังถกู กลา วถงึ (active or current
object) ดงั น้นั การบงบอก this.name ก็หมายถึง filed: name ของ object น้ี
แต this ก็มีความหมายอกี อนั หนึ่งก็คือ ไปเรียกใช constructor ที่อยูภ ายใน class เดียวกนั ดงั ท่เี รา
ไดแสดงใหดูใน class Mean เชน this(value1) หรือ this(value1, value2) – บรรทดั ท่ี 18 และ 25
ตามลําดับ
5.5 การ overload method
เนื่องจากวา constructor ก็เปน method ชนิดหนง่ึ ดงั นัน้ ถา เราสามารถท่จี ะ overload constructor
ไดเ รากส็ ามารถท่ีจะ overload method ไดเชน กัน เพราะฉะนัน้ เราจะมาดูเรอ่ื งการ overload
method ซึ่งก็ไมแ ตกตางจากการ overload constructor เทาใดนัก เรามาเริ่มตน ดวย method ท่ี
แสดงผลออกทางหนาจอ จากตวั แปรชนิดตา ง ๆ ท่สี ง เขาไปยงั method น้ี
1: /**
2: Show how to overload methods to display different types
3: of parameters passing to them
4: */
5:
6: import static java.lang.System.out;
7:
8: class Ball {
9: private double x, y, z;
10:
11: //constructor
12: Ball() {
13: x = y = z = 0.0;
14: }
15:
16: //display coordinates
17: public void display() {
18: out.printf("(%.1f, %.1f, %.1f)%n", x, y, z);
19: }
20: }
21:
22: //a class that creates balls with different types of values
23: class Overload {
24: public static void main(String[] args) {
25: Ball ball = new Ball(); //create object
26:
27: display(25); //display int
28: display(350.00); //display double
29: display("Overloading."); //display string
30: display('A'); //display char
31: display(ball); //display object
188
บทท่ี 5: Objects และ Classes
32: } intro. to Java (FEU.faa)
33: //accept int as a parameter
34: public static void display(int data) {
35: out.println(data);
36: }
37:
//accept double as a parameter
38: public static void display(double data) {
39:
40: out.println(data);
}
41:
42: //accept string as a parameter
public static void display(String data) {
43:
44: out.println(data);
45: }
46: //accept char as a parameter
47: public static void display(char data) {
48:
out.println(data);
49: }
50: //accept object as a parameter
51: public static void display(Ball blue) {
52: blue.display(); //calling display() from class Ball
53: }
54:
55:
56:
57:
58: }
โปรแกรม Overload.java สราง method display() เพอ่ื รองรบั parameter ตาง ๆ จํานวน 5 ตัว คือ
รบั int รับ double รบั string รบั char และรับ object และกเ็ ชน เดียวกับการ overload constructor
method ที่เราเขียนขึน้ ตางก็มี signature ทีไ่ มเ หมอื นกนั ดงั น้ัน java ก็สามารถหา method ที่
ถูกตอ งตามการเรียกใช ผลลพั ธท ่ีไดจ ากการ run โปรแกรมคือ
25
350.0
Overloading.
A
(0.0, 0.0, 0.0)
การใช overload นั้นมขี อดใี นการเขยี นโปรแกรมคือ เราไมจําเปน ตองหาชอ่ื อ่ืน ๆ ทเี่ หมาะสมกับ
หนาท่ขี อง method นัน้ ๆ นอกเหนอื จากท่ีเราไดเ ลอื กไวแ ลว และการใชช ่ือเดียวเพ่ือรองรบั
parameter หลายตัวทาํ ใหผ ูใชไ มตองคนหา method ตัวอ่ืน ทท่ี าํ หนา ท่แี บบเดียวกนั ตวั Java เองก็
ไดส ราง method ไวมากมายทีม่ ีการใช overload ในการสรางเพอ่ื รองรบั การใชงานของ user ที่มี
ความหลากหลายของขอมูลทีส่ ง เขาไปยัง method นัน้ ๆ ทําใหผูใชไ มต อ งเสยี เวลาในการคนหา
method ทตี่ วั เองตองการใช เพือ่ ใหเกดิ ความเขา ใจมากข้ึนเรามาลองดูการ overload method อีก
สักตัวอยางหนง่ึ
1: /**
2: method overloading
3: */
4:
5: import static java.lang.System.out;
6:
7: class FindMax {
8: public static void main(String[] args) {
9: String str1 = "Chiang Mai";
10: String str2 = "Chiang Rai";
11: String str3 = "Chiang San";
12:
13: out.printf("Max of (%s and %s) is %s%n",
14: str1, str2, max(str1, str2));
15: out.printf("Max of (%s, %s, and %s) is %s%n",
16: str1, str2, str3, max(str1, str2, str3));
17: }
18:
19: private static String max(String s1, String s2) {
20: if(s1.compareTo(s2) > 0)
21: return s1;
22: return s2;
189
เรม่ิ ตนการเขียนโปรแกรมดวย Java
23: } intro. to Java (FEU.faa)
24: private static String max(String s1, String s2, String s3) {
25: return max(max(s1, s2), s3);
26: }
27:
28: }
ในโปรแกรม FindMax.java เรากําหนดใหม ี method max() 2 ตวั โดยที่ตวั หนงึ่ มี parameter 2 ตวั
และอีกตัวหนงึ่ มี parameter 3 ตวั และ Java จะเรยี กใช max() ไดถ กู ตอ งตาม signature ทไ่ี ด
กําหนดไว เรายงั ไดแ สดงการเรียกใช max() ภายใน max() อีกตัวดวย (บรรทดั ท่ี 26)
5.5.1 การสง parameter แบบไมจ ํากัดจํานวน (Varargs)
Java 1.5 มีโครงสรางอีกตวั หน่ึงท่ยี อมใหเราสง parameter ไปให method แบบไมจํากดั จํานวน
หรอื อาจเรียกวา สงจํานวนของ parameter กี่ตัวก็ไดในการเรียกแตละครั้ง ดังตวั อยา งน้ี
1: /**
2: Using variable-length argument
3: */
4:
5: import static java.lang.System.out;
6:
7: class Varargs {
8: public static void main(String[] args) {
9: int[] number = new int[100];
10:
11: //generate 100 random numbers
12: for(int i = 0; i < number.length; i++)
13: number[i] = (int)(Math.random() * 100) + 1;
14:
15: //get maximum number
16: int max = getMax(number);
17: out.printf("Maximum number is %d%n", max);
18:
19: max = getMax(2, 3, 1, 6, 8, 4);
20: out.printf("Maximum number is %d%n", max);
21:
22: max = getMax(new int[] {5, 4, 6, 3, 2});
23: out.printf("Maximum number is %d%n", max);
24:
25: max = getMax(0);
26: out.printf("Maximum number is %d%n", max);
27: }
28:
29: //calculate maximum number
30: public static int getMax(int... listOfNumbers) {
31: int max = Integer.MIN_VALUE;
32: for(int i : listOfNumbers) {
33: if(i > max)
34: max = i;
35: }
36: return max;
37: }
38: }
ในบรรทดั ที่ 16, 19, 22, 25 ผอู า นจะเหน็ วา เราไดเ รยี กใช method getMax() ดว ย parameter ที่
ตา งกนั ดงั นี้
16: int max = getMax(number);
19: max = getMax(2, 3, 1, 6, 8, 4);
22: max = getMax(new int[] {5, 4, 6, 3, 2});
25: max = getMax(0);
ซ่ึงเปนการเรยี กทีถ่ กู ตอ ง ถงึ แมว าจาํ นวนของ parameter จะตา งกนั กต็ าม ทัง้ นกี้ ็เพราะวา เรา
กําหนดให method getMax() ของเรายอมรบั parameter ที่มีจาํ นวนไมเ ทา กันได ดวยการ
ประกาศใชด งั นี้
public static int getMax(int... listOfNumbers) {
190
บทท่ี 5: Objects และ Classes intro. to Java (FEU.faa)
int max = Integer.MIN_VALUE;
for(int i : listOfNumbers) {
if(i > max)
max = i;
}
return max;
}
ขอกาํ หนดท่ีเราตอ งทาํ ตามกค็ ือ ใชเ ครื่องหมาย . . . (ภาษาอังกฤษอา นวา ellipsis) เปน ตวั กาํ หนด
ความไมแนน อนของจํานวนที่สงมาให method ผูอานควรสังเกตวา การประกาศใช method ใน
ลกั ษณะนไี้ มม ีความยงุ ยากอะไรเลย ในทางตรงกนั ขา มยังเปนการงา ย และเอื้ออาํ นวยความสะดวกให
เรามากกวาดว ยซาํ้ ไป และผลลัพธท เ่ี ราไดจ ากการ run โปรแกรม Varargs.java คอื
Maximum number is 99
Maximum number is 8
Maximum number is 6
Maximum number is 0
ถา เรามี parameter อ่นื ทต่ี องการใชใน method กอนการใช parameter ท่เี หลอื อยู เราจะตอ ง
กาํ หนดให method มี parameter เหลา นน้ั กอ นการใช varargs . . . ดังตวั อยางนี้
1: /**
2: Using variable-length argument
3: */
4:
5: import static java.lang.System.out;
6:
7: class Varargs2 {
8: public static void main(String[] args) {
9: //calling min()
10: min(2, 3, 22, 11, 33, 44, 55);
11: }
12:
13: public static void min(int first, int second, int... rest) {
14: //add first two arguments
15: int sum = first + second;
16: out.printf("%d + %d = %d%n", first, second, sum);
17:
18: //find minimum number of the rest
19: StringBuffer buffer = new StringBuffer();
20: int min = Integer.MAX_VALUE;
21: for(int num : rest) {
22: buffer.append(num + " ");
23: if(num < min)
24: min = num;
25: }
26: //get rid of the last space
27: String s = buffer.substring(0, buffer.length()-1);
28:
29: out.printf("Min of [%s] is %d%n", s, min);
30: }
31: }
ในบรรทดั ที่ 15 เราทาํ การรวมคา ของ parameter 2 ตัวแรกท่ีสงไปให method min() แลวจงึ
แสดงผล หลังจากน้ันเราก็ทาํ การหาคาของ parameter ท่ีมคี านอ ยทีส่ ดุ ในกลมุ ของ parameter ที่
เหลืออยู และเพอ่ื ท่จี ะใหผ อู านเห็นวา method ของเราไมไดเรยี กใช parameter 2 ตัวแรกเราจงึ ทาํ
การเกบ็ คา เหลา น้ันไวใน StringBuffer สาํ หรับการแสดงผล และผลลัพธท ่ีเราไดคือ
2+3=5
Min of [22 11 33 44 55] is 11
5.6 การสราง class ภายใน class (nested class)
ตัวอยางของการสรางและเรียกใช class ทเ่ี ราไดทราบถงึ กอ นหนา น้ี เปนการสรา ง class ที่มเี พยี ง
เฉพาะตวั แปร และ method อยภู ายใน class เทา นน้ั ยงั ไมมขี อ มลู ภายใน class ทต่ี ัวมันเองกเ็ ปน
class เชนเดียวกัน เราจะมาดูถึงวธิ กี ารสรา ง class ภายใน class อยางงา ย ๆ เพื่อใหไ ดร บั ทราบวา
Java ยอมใหม กี ารสรา ง class ภายใน class เชนเดยี วกันกับทีเ่ ราสามารถสราง method อื่น ๆ
191
เรมิ่ ตน การเขยี นโปรแกรมดวย Java intro. to Java (FEU.faa)
เราจะลองเขยี นโปรแกรมตัวอยางแบบงา ย ๆ ท่ี class ซอ นกันอยู
1: /**
2: Shows the use of nested classes
3: */
4:
5: //class Parent
6: class Parent {
7: private String name;
8: Child c = new Child("Galvin"); //create a Child
9:
10: Parent(String n) {
11: name = n;
12: }
13:
14: public void showName() {
15: System.out.println("Parent: " + name);
16: c.showName(); //calling Child's showName()
17: }
18:
19: //class Child (of Parent)
20: class Child {
21: private String name;
22: GrandChild gc = new GrandChild("Jeff");
23:
24: Child(String n) {
25: name = n;
26: }
27:
28: public void showName() {
29: System.out.println("Child: " + name);
30: gc.showName(); //calling GrandChild's showName()
31: }
32:
33: //class Grandchild (of Parent)
34: class GrandChild {
35: private String name;
36:
37: GrandChild(String n) {
38: name = n;
39: }
40:
41: public void showName() {
42: System.out.println("GrandChild: " + name);
43: }
44: }//class GrandChild
45: }//class Child
46: }//class Parent
47:
48: //testing module
49: class NestedClass {
50: public static void main(String[] args) {
51: Parent p = new Parent("Rebecca");
52:
53: p.showName();
54: }
55: }
โปรแกรม NestedClass.java สรา ง object จาก class Parent หน่ึงตัว แสดงขอมูลทอี่ ยูใน class
ผานทาง method showName() ซึง่ ใหผลลัพธ ดงั นี้ คือ
Parent: Rebecca
Child: Galvin
GrandChild: Jeff
class Parent ของเราไดสราง class อีก class หนง่ึ ท่อี ยภู ายในชื่อ Child และ class Child ก็ไดส ราง
class อีก class หน่งึ ชอ่ื GrandChild โดยทกุ class จะมี method ชื่อ showName() ซึ่งเอาไวใ ชใน
การแสดงคาของตวั แปรของแตล ะ class ไปยังหนาจอ เราไดส รา ง object จาก class Child ภายใน
class Parent ชือ่ c และเราเรียก method showName() ของ class Child จาก method
192
บทที่ 5: Objects และ Classes intro. to Java (FEU.faa)
showName() ของ class Parent ในทาํ นองเดียวกันรากไ็ ดสราง object จาก class GrandChild
ภายใน class Child และก็เรยี ก method showName() ของ class GrandChild จาก method
showName() ของ class Child ดวย เพราะฉะน้นั ขั้นตอนของการ execute คือ
Parent.showName() Æ Child.showName() Æ GrandChild.showName()
เราสามารถท่จี ะสรา ง object จาก class ท่อี ยดู า นในผานทาง object ทอี่ ยูด านนอก ดงั เชนตวั อยางนี้
class NestedClass {
public static void main(String[] args) {
Parent p = new Parent("Rebecca");
p.showName();
Parent.Child newChild = p.new Child("John");
Parent.Child.GrandChild newGrandChild = newChild.new GrandChild("Jen");
newChild.showName();
newGrandChild.showName();
}
}
เราเพิ่มประโยคใหมเ ขา กบั class NestedClass ของเราเพื่อแสดงการสราง object จาก class ทอ่ี ยู
ภายใน ประโยค
Parent.Child newChild = p.new Child("John");
สราง object จาก class Child ผานทาง object ที่มาจาก class Parent ดวยการเรียกใช p.new
Child("John") เราตองทําการสรางผานทาง object ของ class Parent เทานั้นเราไมส ามารถท่จี ะ
สราง object จาก class Child ผานทาง class Parent โดยตรง เชน ประโยค
Parent.Child newChild = Parent.new Child("John");
จะไมไ ดร บั การ compile และ Java จะฟองดวย error ทันที
การสราง object จาก class GrandChild ผานทาง class ท่ีอยภู ายนอกทัง้ สองกค็ ลา ย ๆ กัน
ผลลพั ธของการ run โปรแกรมท่ีถกู ดัดแปลงแลว คือ
Parent: Rebecca
Child: Galvin
GrandChild: Jeff
Child: John
GrandChild: Jeff
GrandChild: Jen
เนอื่ งจากวาเราสรา ง object ของ class Child ผา นทาง class Parent ดังนั้นเมอื่ เรยี กใช method
showName() เราจึงไดผลลัพธ
Child: John
GrandChild: Jeff
อีกครงั้ หนึง่ สวน object ทสี่ รา งขึ้นใหมจ าก class GrandChild เมอ่ื เรียก method showName() เรา
จึงไดเ พียงแต GrandChild: Jen เทา นนั้
ตัวอยา งโปรแกรมการสราง nested class ที่เห็นเปน เพียงแคต วั อยา งทีแ่ สดงใหด ถู งึ การสราง nested
class เทานน้ั การออกแบบ nested class ตอ งคาํ นึงถงึ ความสมั พนั ธของท้ัง class ท่อี ยูดา นนอก
และ class ที่อยูด านในวามคี วามสัมพันธกนั อยางไร ถา ความสัมพนั ธนน้ั สามารถทจ่ี ะเขียน class
แยกกันออกมาได การออกแบบก็ควรใหเ ปน class ท่ีแยกกันอยู เพราะจะทาํ ใหก ารออกแบบทําได
งายกวา การสรางและเรยี กใช object กจ็ ะไมซับซอ นเทา ใดนัก
มาถึงตอนนเ้ี ราไดท ราบถงึ การสรา ง class การออกแบบ method และการสรา ง object จาก class
พอสมควร ตวั อยา งที่จะแสดงใหด ตู อไปเปนความพยายามทจ่ี ะออกแบบ class MyArray ขน้ึ มาใช
งาน เพ่ือท่จี ะแสดงใหเ หน็ ถึงศกั ยภาพของการใช Java ในการเขียนโปรแกรม
193
เร่ิมตน การเขยี นโปรแกรมดว ย Java
5.6.1 ตัวอยางการสราง class: MyArray intro. to Java (FEU.faa)
class MyArray ทเ่ี ราสรา งข้ึนจะกําหนดใหเปน array ทใ่ี ชเ ก็บขอมูลทีม่ ชี นิดเปน Comparable2 ซึ่ง
ขอ มูลชนดิ นีเ้ ปน object ชนิดหนงึ่ ทเี่ ราสามารถทําการเปรียบเทียบได และมคี วามยืดหยุน ในการ
ทาํ งานกับขอ มลู ตา ง ๆ ท้ังนแี้ ละทงั้ นน้ั class MyArray เปน เพียงแคตวั อยางตวั อยางหน่งึ เทานั้น
ผูอานสามารถท่จี ะทําไดม ากกวา ที่โปรแกรมตัวอยางนแี้ สดงใหดู
1: /**
2: Class of comparable array
3: */
4:
5: import static java.lang.System.out;
6:
7: class MyArray {
8: private Comparable []arr; //array of comparable objects
9: private int maxSize; //maximum size of array
10: private int count; //number of items in array
11:
12: //default constructor
13: MyArray() {
14: count = 0; //no item as yet
15: maxSize = 10; //default maximum size
16: arr = new Comparable[maxSize]; //allocate space for arr
17: }
18:
19: //constructor
20: MyArray(int size) {
21: count = 0; //no item as yet
22: maxSize = size; //set maximum size
23: arr = new Comparable[maxSize]; //allocate space for arr
24: }
25:
26: //method to add item into arr
27: public void add(Comparable item) {
28: //expand capacity if arr is full
29: if(count == maxSize) {
30: //double arr's size
31: maxSize *= 2;
32: //create temporary array
33: Comparable []temp = new Comparable[maxSize];
34: //copy items into new array: temp
35: System.arraycopy(arr, 0, temp, 0, arr.length);
36: //refer arr to temp
37: arr = temp;
38: }
39: arr[count++] = item; //add new object into arr
40: }
41:
42: //overload method add to accommodate double
43: public void add(double item) {
44: add(String.valueOf(item));
45: }
46:
47: //overload method add to accommodate int
48: public void add(int item) {
49: add(String.valueOf(item));
50: }
51:
52: //return formatted output when user uses println()
53: //10 items per line
54: public String toString() {
55: //create new buffer to hold data
56: StringBuffer buffer = new StringBuffer();
2 Java รุนกอน 1.5 เราสามารถสราง array เก็บขอ มูลชนดิ Object ไดง าย ๆ โดยไมตอ งคํานงึ ถึงชนดิ ของขอ มลู จริง ๆ ที่
ตองการเกบ็ เชน เราอาจเกบ็ ขอมูลที่เปน String, Integer, หรอื ชนดิ อนื่ ๆ ที่อยูภายใต Object แต Java 1.5 ตองการความ
เปนเอกเทศของ Object จงึ บังคับใหเราตองกําหนดชนิดของ Object ทเี่ ราตองการใช ในขณะที่โปรแกรมกําลัง execute เพอ่ื
ไมต องมีการเปลีย่ นชนิดของ Object กลบั ไปกลับมา ดงั น้นั เราจงึ ตอ งใช interface Comparable แทนเพื่อใหเ ราสามารถใช
Object หลากหลายชนดิ ได Java API ไดแ สดงถึง class ตา ง ๆ ท่ีไดสรา งขึน้ จาก interface Comparable นี้ และเรากไ็ ดใช
class String และ Class Integer เปนชนดิ ของขอมูลใน array ของเราดังนนั้ เราจงึ ไมม ปี ญหาในการกาํ หนดชนิดของขอมูล
194
บทท่ี 5: Objects และ Classes intro. to Java (FEU.faa)
57: for(int i = 0; i < maxSize; i++) {
58: //append newline if this line already has 10 items
59: if(i != 0 && i % 10 == 0)
60: buffer.append("\n");
61: //stop appending when there is no item left (null)
62: if(arr[i] == null)
63: break;
64: //left align data with width = 5
65: String out = String.format("%5s", arr[i]);
66: buffer.append(out);
67: }
68: //returning an output String
69: return new String(buffer + "\n");
70: }
71: }
เรากําหนดใหม ี constructor สองตัว โดยท่ีตวั แรกเปน default constructor ทก่ี ําหนดใหข นาดของ
array มคี วามจคุ รงั้ แรกไดเ พียง 10 ตวั สวนตวั ทสี่ องเปน constructor ที่ผูใชสามารถกําหนดขนาด
ของ array ได เราไดออกแบบให array ของเราเปน array แบบยืดหยนุ หรอื ท่เี รยี กวา dynamic
array โดยเรากําหนดใหมีการขยายขนาดของ array ใหเปนสองเทา ของขนาดเดิมถา มกี ารใสขอ มลู
เกินจํานวนท่ี array สามารถรองรับได ใน method add()
public void add(Comparable item) {
//expand capacity if arr is full
if(count == maxSize) {
//double arr's size
maxSize *= 2;
//create temporary array
Comparable []temp = new Comparable[maxSize];
//copy items into new array: temp
System.arraycopy(arr, 0, temp, 0, arr.length);
//refer arr to temp
arr = temp;
}
arr[count++] = item; //add new object into arr
}
method add() ของเราจะตรวจสอบคาของ count (จํานวนของขอ มูลทม่ี อี ยใู น array) กบั maxSize
(ความจุสงู สุดทสี่ ามารถเกบ็ ขอมลู ได) วาเปน คาเดียวกนั หรือไม ถา เปนคาเดียวกันเราจะขยายขนาด
ของ array ออกเปนสองเทา ดวยการสราง array ตัวใหมชื่อ temp ท่มี คี วามยาวเปนสองเทาของ
array ตวั เดิม
maxSize *= 2;
Comparable []temp = new Comparable [maxSize];
หลังจากนั้นเรากท็ ําการโยกยายขอ มูลจาก array ตัวเกา สู array temp ดวยการใชคาํ ส่งั
System.arraycopy(arr, 0, temp, 0, arr.length);
คาํ สั่งน้จี ะทาํ การยายขอมูลจาก arr เรมิ่ ตน ที่ index = 0 ไปสู temp เร่ิมตนที่ index 0 จนกวาจะหมด
ความยาวที่กําหนดให (arr.length) ซ่ึงกค็ ือจาํ นวนของขอ มลู ที่อยใู น arr ทงั้ หมด
เม่อื โยกยา ยขอมลู เสร็จแลว เรากอ็ างถึง array ตัวใหมดวย array ตัวเดมิ ของเราคอื arr ดวยคําสงั่
arr = temp;
เรายังไดท ําการ overload method add() ของเราเพ่ือใหสามารถรองรบั การเพ่มิ ขอมลู ที่เปน double
และ int เขา สู array ของเราได วธิ ีการแบบนี้ไมค อ ยจะดีสักเทาไร เพราะเปนการนําเอาขอ มลู ท่ไี มใช
ชนิดเดียวกนั (โดยตรง) เขาไปเกบ็ ไวใ น array ซึง่ ถา หากมกี ระบวนการอ่ืน ๆ ท่ีเราตอ งการทํากับ
ขอมลู เหลา นัน้ เราจะตองเสยี เวลาในการตรวจสอบชนิดของขอ มูลทกุ ตัวท่ีมอี ยใู น array ของเรา
เราทาํ การ overload ดว ยการใช method ของ class String คือ String.valueOf() ดังท่ีเหน็ นี้
public void add(double item) {
add(String.valueOf(item));
195
เร่ิมตนการเขียนโปรแกรมดวย Java
}
เนอ่ื งจากวา String เปน Object ชนดิ หนง่ึ ดังน้นั การ add String เขา สู array ของเราจึงไมมีปญหา intro. to Java (FEU.faa)
อะไร (ดู footnote: 2) หลังจากนัน้ เราไดเ ขียนโปรแกรมเพอ่ื ตรวจสอบ ดงั น้ี
1: /**
2: Test MyArray class
3: */
4:
5: class TestMyArray {
6: public static void main(String[] args) {
7: //create array of 10 objects
8: MyArray array = new MyArray(10);
9:
10: //add 40 objects into array randomly
11: int count = 0;
12: while(count < 40) {
13: int data = (int)(Math.random() * 100 + 1);
14: array.add(new Integer(data));
15: ++count;
16: }
17: //display array's content
18: System.out.println(array);
19:
20: array.add(45.23); //add 2 doubles
21: array.add(88.23);
22:
23: array.add(89); //add 2 ints
24: array.add(12);
25: System.out.println(array);
26: }
27: }
เรากไ็ ดผ ลลัพธ ดงั นี้
66 28 90 93 55 80 15 26 4 50
50 94 65 38 5 56 51 96 84 77
70 54 94 21 69 55 11 86 85 83
55 53 95 6 22 90 73 73 43 60
66 28 90 93 55 80 15 26 4 50
50 94 65 38 5 56 51 96 84 77
70 54 94 21 69 55 11 86 85 83
55 53 95 6 22 90 73 73 43 60
45.2388.23 89 12
ผอู า นควรสงั เกตถึงผลลัพธท ไ่ี ดโ ดยเฉพาะขอมูลในบรรทัดสุดทาย (ทีเ่ ราไดเพม่ิ ขอมลู ทเี่ ปน double
และ int หลังจากการ display ครง้ั แรก)
สว นประกอบท่ีสาํ คัญอกี สว นหน่งึ ที่ตอ งกลา วไวใ นท่นี ี้ คือ method toString() และกอนที่จะพูดถงึ
method toString() เราควรดูประโยคอีกประโยคหน่งึ กอ น นัน่ ก็คอื
System.out.println(array);
ประโยค System.our.println() จะรับเฉพาะขอมูลที่เปน String หรอื primitive datatype ที่เราได
พดู ถึงกอ นหนาน้ี แตส่ิงท่ีเราสงไปใหเปน object จาก class MyArray ทาํ ไมเราถงึ ทําได?
เราสง object ไปให System.out.println() ไดกเ็ พราะวาเราไดเ ขียน method toString() รองรับไว
เรียบรอยแลว เม่ือไรกต็ ามท่ี Java เห็นขอมลู ท่ีไมใช String หรอื primitive datatype Java จะทาํ
การคน หา method toString() ถา มี Java ก็จะใช method toString() น้ัน แตถา ไมม กี จ็ ะฟอ งดว ย
error ทันที เรามาดกู ันวา เราเขียน method toString() อยา งไร
public String toString() {
//create new buffer to hold data
StringBuffer buffer = new StringBuffer();
for(int i = 0; i < maxSize; i++) {
//append newline if this line already has 10 items
196