The words you are searching are inside this book. To get more targeted content, please make full-text search by clicking here.

Introduction to Programming Java Language

Discover the best professional documents and content resources in AnyFlip Document Base.
Search
Published by ปิติ เกตุ, 2021-03-22 04:12:52

Introduction to Programming Java Language

Introduction to Programming Java Language

บทท่ี 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


Click to View FlipBook Version