204
เขียนโปรแกรมเชิงวัตถุดวย

เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

  • Upload
    others

  • View
    9

  • Download
    0

Embed Size (px)

Citation preview

Page 1: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

เขียนโปรแกรมเชิงวัตถุดวย

Page 2: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

เขียนโปรแกรมเชิงวัตถุดวย จาวา 2

เขียนโดย นรินทร โอฬารกิจอนันต ซันจาวา 2 เซอรติฟายด โปรแกรมเมอร (SJCP) เน้ือหาท้ังหมดในหนังสือเลมน้ีเปนลิขสิทธ์ิของ นรินทร โอฬารกิจอนันต แตเพียงผูเดียว หามมิใหผูใดแกไข เพิ่มเติม สวนใดสวนหนึ่งหรือทั้งหมดของหนังสือหรือนําไปใชเพื่อประโยชนในเชิงการคา เวนเสียแตวาไดรับอนุญาตจากเจาของกอน อนึ่งผูเขียนไมขอรับผิดชอบความเสียหายที่เกิดขึ้นของผูอาน ในกรณีที่มีบางสวนของหนังสือที่ไมถูกตองหรือพิมพผิดแตประการใด ประวัติการแจกจาย

ฉบับทดลอง แจกจายเมื่อ วันที่ ๑๗ มกราคม พุทธศักราช ๒๕๔๕

ฉบับจริง แจกจายเมื่อ วันที่ ๓๑ มกราคม พุทธศักราช ๒๕๔๕

บรรณานุกรม -A Programmer’s Guide to Java Certification, A Comprehensive Premier by Khalid A. Mughal and Rolf W. Rasmussen, Addison-Wesley, ISBN 0-201-59614-8 -The Java Tutorials : A short course on the basics by Mary Campione, Kathy Walrath and Alison Huml, Addison-Westley, ISBN 0-201-70393-9 -Essential Java 2 Fast : How to develop applications and applets with Java 2 (Essential Series) by John Cowell, Spinger Verlag ,ISBN 1-852-33071-6 โครงการหนังสอืจาวาในอนาคต

-เจเอสพี สําหรับจาวาเวบโปรแกรมเมอร -เอ็นเตอรไพรส จาวาบีน สําหรับองคกรธุรกิจ

-สรางโปรแกรมบนออรแกนไนเซอรดวย เจทูเอ็มอี จาวา เปนเครื่องหมายการคาของบริษัท ซัน ไมโครซิสเต็มท วินโดว เปนเครื่องหมายการคาของบริษัทไมโครซอฟท ยูนิกซ เปนเครื่องหมายการคาของบริษัท เอ็กซโอเพ็น แมคอินทอช เปนเครื่องหมายการคาของบริษัทแอปเปล เนตสเคป เนวิเกเตอร เปนเคร่ืองหมายการคาบริษัทเนตสเคป แจกจายโดย http://www.dekisugi.net/java

ติดตอ [email protected]

Page 3: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

สารบัญ

บทที่ 1 จาวา และ โปรแกรมเชิงวัตถุบทที่ 2 จาวาเวอรชัวนแมทชีน และ จาวาคอมไพลเลอร

บทที่ 3 โปรแกรม Hello Worldบทที่ 4 คาคงตัว และ ตัวแปรพื้นฐาน

บทที่ 5 เครื่องหมายบทที่ 6 บลอคเง่ือนไขบทที่ 7 บลอควนลูป

บทที่ 8 คลาส และ วัตถุบทที่ 9 ตัวแปรอางอิงบทที่ 10 ตัวแปรคลาส

บทที่ 11 อะเรยบทที่ 12 แมธธอส

บทที่ 13 คอนสตรัคเตอรบทที่ 14 ตัวแปรสตริง

บทที่ 15 คลาสสําหรับตัวแปรพ้ืนฐานบทที่ 16 คลาส Mathบทที่ 17 การสืบทอดบทที่ 18 แพจเกจ

บทที่ 19 ตัวกํากับตัวแปรคลาส และแมธธอสบทที่ 20 คลาส Object

บทที่ 21 อินเตอรเฟสบทที่ 22 คอลเล็กชัน่บทที่ 23 เอ็กซเซฟช่ัน

บทที่ 24 เทรด

Page 4: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม
Page 5: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

1จาวา และ โปรแกรมเชิงวัตถุ

ไชโย ในที่สุดคุณก็ตัดสินใจที่จะเรียนรูจาวาอยางจริง ๆ จัง ๆเสียที

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

เราไดยินคําวา จาวา จากอินเตอรเนตมากท่ีสุด แตที่จริงแลวจาวามีใชในเทคโนโลยีรูปแบบอื่นดวย จะวาไปแลว ตนกําเนิดของจาวาไมไดเร่ิมจากอินเตอรเนต แตเริ่มจากการพัฒนาภาษาคอมพิวเตอรที่ใชสําหรับสรางโปรแกรมขนาดจ๋ิวบนเคร่ืองใชอิเล็กทรอนิกส ปจจุบันจาวามีที่ใชอยูทุกหนทุกแหง ตั้งแต เคร่ืองใชอิเล็กทรอนิกส ปาลมออแกนไนเซอร คอมพิวเตอรสวนบุคคล จนถึงเครื่องคอมพิวเตอรแมขายระดับองคกร แต จาวา เปนที่รูจักในวงกวางเปนครั้งแรกตอนที่มันถูกนําเขาไปใชในการสรางสีสันใหกับโฮมเพจบนอินเตอรเนต ทําใหหลายคนรูจักจาวาในฐานะของกราฟฟกเคลื่อนไหวบนโฮมเพจ หรือท่ีเราเรียกวา จาวาแอ็พเลตต ทั้งที่ความจริงแลวจาวามีความหมายกวางกวานั้น

บนอินเตอรเนตมีเทคโนโลยีอีกตัวหนึ่งที่มีชื่อวา จาวาสคริปต ซึ่งเปนภาษาที่ใชสําหรับกํากับเบราเซอรใหแสดงผลโฮมเพจใหมีลูกเลนตาง ๆตามใจชอบ จาวาสคริปต พัฒนาโดยบริษัทเนตสเคป โดยใชโครงสรางของภาษาจาวาเปนพ้ืนฐาน บางคนนิยามสับสนระหวางจาวา กับจาวาสคริปต ที่จริงแลว จาวาสคริปต ไมถือเปนสวนหนึ่งของจาวา และไมเกี่ยวของกับจาวาแตประการใด

Page 6: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 1 จาวาและโปรแกรมเชงิวัตถุ

6

นิยามของจาวาที่จัดวาเหมาะสมที่สุดมีสองนิยามไดแก จาวาคือภาษาคอมพิวเตอร และจาวาคือแฟลตฟอรม

ภาษาจาวาภาษาจาวา พัฒนาขึ้นโดยบริษัท ซัน ไมโครซิสเตมท ชื่อของ จาวา มาจากชื่อชนิดของกาแฟที่ทีมวิศวกรของซันดื่ม ตอนที่รวมพัฒนาภาษาจาวาตนแบบดวยกัน จาวาเปนเทคโนโลยีเปด ที่มี ซัน เปนผูกํากับทิศทาง และคอยระวังไมใหใครเอาจาวาไปดัดแปลงประยุกตใชในทางที่เบี่ยงเบนออกจากจุดประสงคเดิมของมัน การกําหนดทิศทางโดยซันเปนไปเพื่อใหเกิดความชัดเจนในแงของทิศทางการพัฒนา

ภาษาจาวามีคําส่ังพ้ืนฐานคลายภาษาซีพลัสพลัสเปนอยางมาก นักเขียนโปรแกรมท่ีใชภาษาซีพลัสพลัสสามารถเรียนรูภาษาจาวาไดในเวลาอันรวดเร็ว เหตุผลที่ทีมวิศวกรของซันไมเลือกใชภาษาซีพลัสพลัสในการพัฒนาภาษาสําหรับโปรแกรมขนาดจ๋ิวบนเคร่ืองใชอิเล็กทรอนิกสเปนเพราะ เคร่ืองใชอิเล็กทรอนิกส มีเนื้อที่สําหรับเก็บโปรแกรมจํากัด พวกเขาจึงสรางภาษาคอมพิวเตอรภาษาใหมขึ้นมาใหชื่อวา โอค ซึ่งตั้งชื่อตามตนไมใหญที่อยูในสวนของบานที่ทีมวิศวกรใชเปนสถานที่สําหรับทํางาน ภาษาใหมนี้มีความกระชับมากกวาเดิม แตมีคําส่ังพ้ืนฐานเหมือนภาษาซีพลัสพลัส เน่ืองจากตองการใหนักเขียนโปรแกรมภาษาซีพลัสพลัส ซ่ึงมีอยูมากท่ีสุดในขณะน้ันสรางความคุนเคยไดอยางรวดเร็ว ตอมาพวกเขาเปลี่ยนชื่อภาษาใหมนี้เปน จาวา ตามชื่อชนิดของกาแฟ ที่พวกเขาดื่ม

ภาษาจาวาจัดเปนภาษาคอมพิวเตอรเชิงวัตถุเชนเดียวกับภาษาซีพลัสพลัส แตสิ่งที่ภาษาจาวาตางกับ ภาษาซีพลัสพลัส เปนอยางมาก คือ โปรแกรมภาษาจาวาตองเขียนเปนแบบเชิงวัตถุเทานั้น ในขณะท่ีภาษาซีพลัสพลัส สามารถเขียนแบบเชิงวัตถุ หรือเขียนแบบโครงสราง ก็ได ท่ีเปนเชนน้ีเน่ืองจากภาษาซีพลัสพลัสมีตนกําเนิดมาจากภาษาซี ซ่ึงเปนภาษาแบบโครงสราง ดังน้ันภาษาซีพลัสพลัสจึงตองสนับสนุนการเขียนโปรแกรมแบบโครงสรางดวยเพื่อใหเขากันไดกับภาษาซี อยางไรก็ตาม ภาษาแบบโครงสรางเปนเทคโนโลยีที่ลาสมัย โปรแกรมประยุกตในทองตลาดปจจุบันนี้ลวนแตเขียนดวยภาษาเชิงวัตถุทั้งสิ้น จาวาจึงไมสนับสนุนภาษาโครงสราง

จาวาแฟลตฟอรมนิยามที่เหมาะสมอันหนึ่งของจาวาคือ จาวาเปน แฟลตฟอรม คําวา แฟลตฟอรม โดยทั่วไปมีความหมายใกลเคียงกับคําวา ระบบปฏิบัติการ ตัวอยางเชน ระบบปฏิบัติการวินโดว บางทีเราก็เรียกวา แฟลตฟอรมวินโดว ความหมายตรงตัวของคําวา แฟลตฟอรม ในพจนานุกรมหมายถึง สถานี เชน ชานชลาสถานีรถไฟ สาเหตุท่ีเราเรียกระบบปฏิบัติการวาเปน แฟลตฟอรม เปนเพราะ เวลาเราเขียนโปรแกรมประยุกตอะไรก็ตามขึ้นมา เวลาเราจะใชงานมนั เราจะตองรันมันบนระบบปฏิบัติการ ตัวอยางเชน ไมโครซอฟทเวิรด จะใชงานไดตองรันบนระบบปฏิบัติการวินโดว ระบบปฏิบัติการวินโดวจึงเปนเสมือนสถานีปฏิบัติการสําหรับโปรแกรมไมโครซอฟทเวิรด

โปรแกรมภาษาจาวา ไมเหมือนโปรแกรมที่เขียนขึ้นดวยภาษาคอมพิวเตอรภาษาอื่น โปรแกรมภาษาจาวาไมไดรันบนระบบปฏิบัติการ แตรันบนแฟลตฟอรมเสมือน ซ่ึงเราเรียกวา จาวาแฟลตฟอรม หรือ จาวาเวอรชัวนแมทชีน ดัวยเหตุนี้เราจึงกลาววา จาวา เปนแฟลตฟอรม

Page 7: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 1 จาวาและโปรแกรมเชงิวัตถุ

7

จาวาเวอรชัวนแมทชีน เปนสิ่งที่ซอนโปรแกรมภาษาจาวาจากระบบปฏิบัติการของเครื่องคอมพิวเตอร โปรแกรมที่เขียนขึ้นดวยภาษาจาวา ไมวาจะนําไปรันบนระบบปฏิบัติการใด มันจะมองไมเห็นความแตกตางของระบบปฏิบัตการที่มันรันอยู เนื่องจากมันไมไดติดตอกับระบบปฏิบัติการของเครื่องคอมพิวเตอรโดยตรง แตมันจะติดตอกับจาวาเวอรชัวนแมทชีนแทน และจาวาเวอรชัวนแมทชีนจะติดตอกับระบบปฏิบัติการอีกที

จาวาเวอรชัวนแมทชีนในทุก ๆระบบปฏิบัติการมีหนาตาเหมือนกันหมด ดังนั้นโปรแกรมที่เขียนขึ้นดวยภาษาจาวาสามารถนําไปรันบนระบบปฏิบัติการใดก็ได หรือกลาวอีกนัยหน่ึงก็คือ จาวาเวอรชัวนแมทชีนก็คือระบบปฏิบัติการสําหรับโปรแกรมภาษาจาวา

รูปที่รูปที่รูปที่รูปที่ 1111----1111 จาวาแฟลตฟอรม จาวาแฟลตฟอรม จาวาแฟลตฟอรม จาวาแฟลตฟอรม

ปกติแลวโปรแกรมประยุกตที่เขียนดวยภาษาอื่น ถาพัฒนาขึ้นมาเพื่อระบบปฏิบัติการใด จําเปนที่จะตัองรันบนระบบปฏิบัตการน้ัน เชน ไมโครซอฟทเวิร็ดสําหรับระบบปฏิบัติการวินโดวจะตองรันบนระบบปฏิบัติการวินโดวเทานั้น ไมสามารถนําไปใชงานบนระบบปฏิบัติการอ่ืนเชน ลินิกซ หรือแมคอินทอชได เนื่องจากระบบปฏิบัติการแตละอันมีความแตกตางกันอยู นี่เปนความไดเปรียบของการเขียนโปรแกรมดวยภาษาจาวา เพราะไมวาจะเขียนขึ้นบนระบบปฏิบัติการใด เม่ือเขียนเสร็จแลวจะสามารถนําไปรันไดบนระบบปฏิบัติการอ่ืนทุกระบบที่มีจาวาเวอรชัวนแมทชีน เราเรียกคุณสมบัตินี้ของโปรแกรมภาษาจาวาวา Write Once, Run Anywhere

นักเขียนโปรแกรมภาษาจาวาจาวาเวอรชัวนแมทชีนไมไดมีอยูแตในเฉพาะโลกของคอมพิวเตอรตั้งโตะเทานั้น แตยังมีอยูบนทุก ๆ สิ่งทุกอยางตั้งแต สมารทการด โทรศัพทมือถือ ปาลมออแกนไนเซอร พีซี เบราเซอร หรือเครื่องคอมพิวเตอรแมขาย การเรียนรูภาษาจาวาจึงเปนการลงทุนที่คุมคาสําหรับนักเขียนโปรแกรม เพราะรูภาษาเดียวแตสามารถนําไปใชพัฒนาโปรแกรมบนอะไรก็ได นักเขียนโปรแกรมภาษาจาวาคนหนึ่งอาจใชภาษาจาวาพัฒนาโปรแกรมบนเครื่องคอมพิวเตอรแมขายที่สํานักงานท่ีตนทํางานอยู ยามวางก็พัฒนาเวบไซตใหบริษัทอื่นเพื่อหารายไดพิเศษดวยภาษาจาวา หรืออาจพฒันาโปรแกรมเล็ก ๆบนปาลมออแกนไนเซอรไวสําหรับแจกเพ่ือนฝูงเปนงานอดิเรกดวยภาษาจาวา การที่ภาษาจาวาทําไดทุกอยาง ทําใหนักเขียนโปรแกรมที่เลือกเรียนภาษาจาวา ไมจําเปนตองเรียนรูภาษาคอมพิวเตอรภาษาอ่ืนอีกเลย เราเรียกแนวคิดน้ีวา 100% pure java

Page 8: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 1 จาวาและโปรแกรมเชงิวัตถุ

8

ขั้นตอนการเขียนโปรแกรมภาษาจาวานั้นไมตางกับการพัฒนาโปรแกรมในภาษาอ่ืนมากนัก การเขียนโปรแกรมเร่ิมตนจากการเขียนคําส่ังภาษาจาวาลงบนเท็กซไฟล เราเรียกไฟลเหลาน้ีวา ซอรสโคด ซึ่งซอรสโคดภาษาจาวาจะตองมีนามสกุลเปน .java เสมอ

เมือ่เขียนโปรแกรมเสร็จแลว เราจะทําการคอมไพลซอรสโคด การคอมไพลซอรสโคค ก็คือการเปล่ียนคําส่ังภาษาจาวาเปนภาษาเฉพาะอยางหนึ่งซึ่งจาวาเวอรชัวนแมทชีนเขาใจ ตัวที่ทําหนาที่ในการคอมไพลซอรสโคคเรียกวา จาวาคอมไพลเลอร ซ่ึงเปนซอรฟแวรท่ีสามารถอานคําส่ังในไฟล .java ของคุณแลวแปลเปนภาษาเฉพาะที่จาวาเวอรชัวนแมทชีนเขาใจได ภาษาเฉพาะที่จาวาเวอรชัวนแมทชีนเขาใจนี้เราเรียกวา จาวาไบตโคด ซ่ึงคอมไพลเลอรจะเก็บจาวาไบตโคดที่ไดไวในไฟลนามสกุล .class ไฟลนามสกุล .class ท่ีไดจากจาวาคอมไพลเลอรน่ีเองคือตัวโปรแกรมที่แทจริงของคุณ เมื่อใดที่คุณตองการรันโปรแกรมที่คุณเขียนขึ้น คุณก็เพียงแตนําไฟล .class ไปรันบนจาวาเวอรชัวนแมทชีน จาวาเวอรชัวนแมทชีนเขาใจจาวาไบตโคดและจะทํางานตามคําสั่งในโปรแกรมที่คุณเขียนขึ้นโดยการอานจากจาวาไบตโคด สรุปข้ันตอนการพัฒนาโปรแกรมไดดงในรูป

รูปที่ รูปที่ รูปที่ รูปที่ 1111----2222 ขั้นตอนการพัฒนาโปรแกรมภาษาจาวาขั้นตอนการพัฒนาโปรแกรมภาษาจาวาขั้นตอนการพัฒนาโปรแกรมภาษาจาวาขั้นตอนการพัฒนาโปรแกรมภาษาจาวา

จําไววา คุณอาจเขาใจภาษาจาวาแตจาวาเวอรชัวนแมทชีนไมเขาใจ จาวาเวอรชัวนแมทชีนเขาใจจาวาไบตโคดซึ่งคุณอานไมรูเร่ือง คอมไพเลอรก็คือตัวกลางที่จะแปลภาษาจาวาที่คุณเขียนใหกลายเปนจาวาไบตโคดน้ันเอง

โปรแกรมเชิงวัตถุการเขียนโปรแกรมคอมพิวเตอรมีสองแบบ คือ การเขียนโปรแกรมแบบโครงสราง และการเขียนโปรแกรมเชิงวัตถุ

การเขียนโปรแกรมแบบโครงสรางเปนการเขียนโปรแกรมแบบที่มนุษยคุนเคย คือ การเขียนคําส่ังเรียงตอกันไปเร่ือย ๆทีละบรรทัด โปรแกรมจะเริ่มทํางานจากคําสั่งแรกสุดเรื่อยไปจนถึงคําสั่งทายสุด เปนอันจบโปรแกรม อาจมกีาร

Page 9: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 1 จาวาและโปรแกรมเชงิวัตถุ

9

สรางเปนโปรแกรมยอย ๆ ในโปรแกรมใหญบาง เพ่ือลดคําส่ังท่ีซํ้าซอน แตหลักการกวาง ๆยังคงเหมือนเดิม ตัวอยางของภาษาที่มีวิธีการเขียนโปรแกรมเปนแบบโครงสรางไดแก ภาษาเบสิก ภาษาโคบอล ภาษาฟอรแทรน ภาษาปาสคาล และ ภาษาซี

การเขียนโปรแกรมเชิงวัตถุ มีการสรางวัตถุสมมติขึ้นมากอน แลวเขียนคําสั่งนิยามวัตถุนั้นจนสามารถทําใหวัตถุนั้นทํางานตามท่ีเราตองการได ซอรสโคดของโปรแกรมเชิงวัตถุแทนที่จะเปนคําสั่งเขียนเรียงตอกันไปเร่ือย ๆ จะเปนนิยามของวัตถุเขียนเรียงตอไปเรื่อย ๆแทน และโปรแกรมจะทํางานไดเองถาวัตถุนั้นถูกนิยามขึ้นอยางเหมาะสม การเขียนโปรแกรมเชิงวัตถุตองใชเวลาในการศึกษานานพอสมควร โดยเฉพาะอยางยิ่งนักเขียนโปรแกรมตองมีความชํานาญในการสรางวัตถุสมมติที่ทํางานตามอยางที่เราตองการได โปรแกรมประยุกตที่เราใชงานจริงในปจจุบันลวนแลวแตเขียนดวยโปรแกรมเชิงวัตถุทั้งสิ้น การศึกษาการเขียนโปรแกรมเชิงวัตถุจึงเปนสิ่งที่นักเขียนโปรแกรมรุนใหมทุกคนควรจะฝกฝนไว ตัวอยางของภาษาที่มีการเขียนโปรแกรมแบบเชิงวัตถุคือ ภาษาจาวา และภาษาซีพลัสพลัส (ภาษาซีพลัสพลัสเขียนไดทั้งแบบโครงสรางและวัตถุ)

การที่โปรแกรมภาษาจาวาตองเขียนเปนแบบเชิงวัตถุเสมอ จัดวาเปนท้ังจุดเดนและจุดดอยของภาษาจาวา การท่ีภาษาจาวาไมสนับสนุนการเขียนโปรแกรมแบบโครงสราง ซึ่งเปนวิธีการเขียนโปรแกรมที่ลาสมัย ทําใหภาษาจาวามีความกระทัดรัดมากกวาภาษาซีพลัสพลัส แตในเวลาเดียวกันก็ทําใหตองใชเวลาศึกษานาน โดยเฉพาะอยางยิ่งคนที่ไมใชนักเขียนโปรแกรมมืออาชีพ เพราะการเขียนโปรแกรมเชงิวัตถุ ไมใชเร่ืองท่ีจะเรียนรูไดในเวลาอันรวดเร็ว

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

จุดมุงหมายของหนังสือเลมนี้ คือ ตองการใหผูอานมีความเขาใจการเชิงโปรแกรมเชิงวัตถุดีพอที่จะนําภาษาจาวาไปใชในเชิงประยุกตได ดังนั้นจึงไมมีการกลาวถึงทฤษฎีของการเขียนโปรแกรมเชิงวัตถุอยางละเอียดลึกซ้ึง เพราะจะทําใหมีลักษณะเปนวิชาการมากเกินไป ในขณะเดียวกันก็จะไมมีการกลาวถึงการนําภาษาจาวาไปใชในเชิงประยุกตมากนัก เพราะไมตองการใหเนื้อหาของหนังสือเยิ่นเยอมากเกินไปจนเสียวัตถปุระสงคหลักของหนังสือ หนังสือเลมน้ีจึงเปนจุดเริ่มตนที่ดีสําหรับผูที่ตองการใชภาษาจาวาในการทํางานจริง ๆ แตหนังสือเลมนี้ยังไมเพียงพอสําหรับการนําภาษาจาวาไปใชงานจริง ขั้นตอนตอไปคือ ผูอานตองศึกษาการนําจาวาไปใชงานจากหนังสือเลมอื่น ประโยชนของหนังสือเลมน้ีคือ ชวยใหผูอานศึกษาหนังสือเหลานั้นไดงายขึ้น

จาวา 2ภาษาจาวามีการพัฒนาอยางตอเนื่อง โดยที่ ซัน เปนผูกําหนดวาโครงสรางภาษาจาวา และคําส่ังตาง ๆ ตองมีหนาตาเปนอยางไร และออกเปนขอกําหนดออกมา ภาษาจาวาตั้งแตเวอรชั่น 1.2 ขึ้นไป มีชื่อเรียกใหมวา จาวา 2 ในหนังสือเลมน้ีเราครอบคลุมเน้ือหาของภาษาจาวาถึงเวอรช่ัน 1.2 แตเพ่ือความกระชับในการส่ือสาร เราจะยังคงใชคํา

Page 10: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 1 จาวาและโปรแกรมเชงิวัตถุ

10

วา จาวา เฉย ๆ อยู คุณสามารถคนหาขอมูลใหม ๆเก่ียวกับ จาวา โดยเฉพาะจาวาเวอรชั่นใหมลาสุดไดจาก http://java.sun.com/j2se ซึ่งมีการเปลี่ยนแปลงอยูอยางสม่ําเสมอ

รูปที่รูปที่รูปที่รูปที่ 1111----3333 http://java.sun.com/j2se

จาวาเปนเทคโนโลยีเปดซึ่งมี ซัน เปนผูกําหนดหนาตาของคําส่ัง ดังน้ัน จะมีบริษัทผลิตซอฟทแวรอื่นอีกจํานวนมากที่ออกผลิตภัณฑที่ใชเทคโนโลยีจาวาออกมา ตัวอยางเชน ไอบีเอ็ม ออราเคิล แมคโครมีเดีย บีอีเอ รวมทั้งซันเองดวย ผลิตภัณฑจากบริษัทเหลานี้ถูกพัฒนาขึ้นตามขอกําหนดของภาษาจาวาอยางเครงครัด ดังน้ัน โปรแกรมภาษาจาวา ของคุณจึงสามารถทํางานบนผลิตภัณฑของบริษัทใดเหลานี้ก็ไดโดยไมตองมีการดัดแปลง ในอนาคตถาทุกบริษัทหันมาใชเทคโนโลยีจาวา ส่ิงท่ีเกิดข้ึนก็คือ ซอฟทแวร จะมีความยุงยากในการเชื่อมตอหรือทํางานประสานกันนอยลง และในขณะเดียวกันบริษัทเหลานี้ก็จะหันมาแขงขันกันในแงของการทําใหผลิตภัณฑของบริษัทตนทํางานไดเร็วกวา แทนที่จะแขงกันเปนผูผูกขาดเทคโนโลยีอยางแตกอน

Page 11: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

2 จาวาเวอรชัวนแมทชีน

และ จาวาคอมไพลเลอร โปรแกรมที่เขียนดวยภาษาจาวารันบน จาวาเวอรชัวนแมทชีน ดังนั้นคุณตองมีจาวาเวอรชัวนแมทชีนบนเครื่องคอมพิวเตอรของคุณถาคุณตองการรันโปรแกรมที่เขียนดวยภาษาจาวา

โปรแกรมที่เขียนดวยภาษาจาวากอนจะนําไปรันไดตองผานการคอมไพลดวย จาวาคอมไพลเลอร กอน เน่ืองจากคุณตองการเปนนักเขียนโปรแกรมภาษาจาวา คุณจึงตองมีทั้งจาวาคอมไพเลอร และ จาวาเวอรชัวนแมทชีน เพ่ือเขียนและลองรันโปรแกรมภาษาจาวา ในบทนี้คุณจะไดเตรียมสิ่งที่จําเปนทั้งสองอยางนี้

เนื่องจากจาวาเปนเทคโนโลยีเปด ดังนั้นคุณอาจจะเลือกใชจาวาเวอรชัวนแมทชีนและจาวาคอมไพลเลอร ของบริษัทใดก็ได ในหนังสือเลมนี้เราจะเลือกใชจาวาเวอรชัวนแมทชีนและจาวาคอมไพลเลอรที่ดาวนโหลดไดจากเวบไซตจาวาของซัน เน่ืองจากเปนท่ีรูจักดีและท่ีสําคัญคือฟรี

อีกส่ิงท่ีคุณตองมีก็คือคอมพิวเตอรสวนบุคคล ซ่ึงจะเปนระบบปฏิบัติการอะไรก็ไดเพราะจาวารันไดทุกระบบปฏิบัติการ ในหนังสือเลมนี้เราเลือกใชระบบปฏิบัติการไมโครซอฟทวินโดว (95/98/Me/2000/XP)เพราะเปนระบบปฏิบัติการที่หาไดงายที่สุด สําหรับผูที่ไมนิยมระบบปฏิบัติการของไมโครซอฟทอาจจะตองลองติดตั้งจาวาเวอรชัวนแมทชีนและจาวาคอมไพลเลอรสําหรับระบบปฏิบัติการที่คุณใชอยูดวยตัวเอง หลังจากติดตั้งเสร็จแลวการใชงานปกติแทบจะไมมีความแตกตางกัน

Page 12: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 2 จาวาเวอรชัวนแมทชีน และจาวาคอมไพลเลอร

12

จาวาเวอรชัวนแมทชีนบนคอมพิวเตอรสวนบุคคลของบริษัทซัน มีชื่อวา JRE หรือ จาวา รันไทม เอ็นไวรอนเมนท สวนจาวาคอมไพลเลอรของซันมีชื่อวา SDK ทั้งสองสามารถดาวนโหลดไดจากเวบไซต http://java.sun.com/j2se

คุณไมจําเปนตองดาวนโหลด JRE เพราะ SDK จะรวม JRE มาใหดวยในตัว

ติดต้ัง SDKใหคุณตอไปยังอินเตอรเนตเพ่ือเขาเวบไซตเจทเูอสอีของซัน http://java.sun.com/j2se เพ่ือดาวนโหลดซอฟทแวรที่มีชื่อวา Java 2 SDK ซึ่งมีการเปลี่ยนเวอรชั่นใหมอยูอยางสม่ําเสมอ คุณสามารถใชเวอรชัน่อะไรก็ไดที่สูงกวาเวอรชั่น 1.2 แตขอแนะนําใหใชเวอรชั่นที่ใหมที่สุดที่ไมใชเวอรชั่นทดสอบ

เลือกระบบปฏิบัติการวินโดว คุณตองเลือกระบบปฏิบัติการใหถูกตองเวลาดาวนโหลดเพราะแมวาโปรแกรมภาษาจาวาจะไมขึ้นกับระบบปฏิบัติการ แตตัวจาวาคอมไพลเลอรและจาวาเวอรชัวนแมทชีนขึ้นกับระบบปฏิบัติการ

เม่ือดาวนโหลดเสร็จแลวก็ใหทําการติดต้ังไดดวยการดับเบิลคลิกที่ไอคอนของไฟลที่ดาวนโหลดมา โปรแกรมจะเขาสูการติดต้ัง SDK ซึ่งเปนวิซซารดเหมือนกันการติดตั้งโปรแกรมบนวินโดวทั่วไปซึ่งคุณควรติดต้ังไดดวยตนเอง

ในข้ันตอนของการเลือกโฟลเดอรท่ีจะติดต้ังโปรแกรม ขอแนะนําใหคุณติดตั้งลงบนโฟลเดอรชื่อวา C:\java เพราะในหนังสือเลมนี้เราจะสมมติวาคุณติดตั้งมันลงในโฟลเดอร C:\java แตในความเปนจริงคุณจะใชชื่อที่มีมาใหหรือตั้งชื่ออื่น ๆก็ได

รูปที่ รูปที่ รูปที่ รูปที่ 2222----1111 ติดตั้ง ติดตั้ง ติดตั้ง ติดตั้ง SDK SDK SDK SDK บนระบบปฏิบัติการวินโดวบนระบบปฏิบัติการวินโดวบนระบบปฏิบัติการวินโดวบนระบบปฏิบัติการวินโดว

เมื่อติดตั้งเสร็จแลวคุณจะไดทุกสิ่งทุกอยางของ SDK จะอยูในโฟลเดอร C:\java ทั้งหมด รวมทั้ง JRE ที่พวงมาดวย

Page 13: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 2 จาวาเวอรชัวนแมทชีน และจาวาคอมไพลเลอร

13

ข้ันตอนการติดต้ังยังไมเสร็จสมบูรณ กอนจะใชงานไดคุณตองระบุ PATH ใหกับระบบปฏิบัติการของคุณเสียกอน ในระบบปฏิบัติการวินโดวทําไดโดยการคลิกเมาสขวาท่ีไอคอน My Computer บนเดสกท็อป แลวเลือก Properties จากนั้นเลือกแทปที่ใหเซตคาตัวแปรระบบได ซึ่งวินโดวแตละชนิดจะมีหนาจอในสวนนี้ไมเหมือนกัน ตัวอยางในภาพเปนการเซตตัวแปรระบบบนวินโดว 2000

รูปที่ รูปที่ รูปที่ รูปที่ 2222----2222 เซตตัวแปรระบบบนวินโดว เซตตัวแปรระบบบนวินโดว เซตตัวแปรระบบบนวินโดว เซตตัวแปรระบบบนวินโดว 2000200020002000

ตัวแปรระบบที่ชื่อ Path จะมีคาเดิมของมันอยูใหคุณคงคาเดิมไวแตเติมตอทายคาเดิมดวย ;C:\java\bin เชนตัวอยางในภาพเปนการเซตคาตัวแปรระบบ Path ใหมบนวินโดว 2000 สังเกต ;C:\java\bin ที่ทายสุดของชอง Variable Value

รูปที่ รูปที่ รูปที่ รูปที่ 2222----3333 การเติม การเติม การเติม การเติม ;C:;C:;C:;C:\\\\javajavajavajava\\\\bin bin bin bin ตอทาย ตัวแปรระบบ ตอทาย ตัวแปรระบบ ตอทาย ตัวแปรระบบ ตอทาย ตัวแปรระบบ PathPathPathPath

เทาน้ีการติดต้ัง SDK ของคุณก็เปนอันเสร็จเรียบรอย

Page 14: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 2 จาวาเวอรชัวนแมทชีน และจาวาคอมไพลเลอร

14

เคล็ดลับ ตัวแปรระบบ path ใชระบุโฟลเดอรที่เปนที่อยูของคําสั่งตาง ๆในดอส ดังน้ันการใส C:\java\bin ไวเปนสวนหนึ่งของตัวแปรระบบ path เปนการบอกใหดอสมองหาคําส่ังจากโฟลเดอรน้ีดวย ซึ่งเปนที่อยูของจาวาคอมไพลเลอร จาวาเวอรชัวนแมทชีน และโปรแกรมสนับสนุนอ่ืน ๆของ SDK

คุณสามารถเซตคาของตัวแปรระบบ path ดวยการส่ังผานดอสโดยตรงก็ได โดยเริ่มจาก

คําสั่งนี้จะแสดงคาปจจุบันของตัวแปร path ออกมาซ่ึงประกอบดวยช่ือโฟลเดอรจํานวนมาก คั้นดวยเครื่องหมาย ; ชื่อโฟลเดอรที่คุณไดอาจแตกตางกันไปแลวแตเครื่อง

เซตคาของตัวแปร path ใหมใหมี C:\java\bin อยูดวย ดวยการส่ังคําส่ังตอไปน้ี

สิ่งที่อยูหลังเครื่องหมายเทากับและอยูหนา ;C:\java\bin คือคาเกาทั้งหมดของตัวแปร path ซึ่งไดจากคําส่ังท่ีแลว เสร็จแลวตรวจสอบคาใหมของตัวแปร path ดวยคําส่ัง

ดอสจะแสดงคาใหมของตัวแปร path ออกมา ซึ่งคุณควรจะเห็น C:\java\bin เปนช่ือสุดทาย

แตขอเสียของการเซตดวยคําส่ังดอสโดยตรงก็คือ คุณตองสั่งใหมทุกครั้งที่เปดหนาจอดอสใหม คุณสามารถกําหนดใหดอสรันคําส่ังน้ีเองโดยอัติโนมัติทุกคร้ังท่ีเปดหนาจอดอสไดดวยการใสคําส่ังน้ีลงไปในไฟล autoexec.bat แตเน่ืองจากไฟล autoexec.bat บนวินโดวแตละเวอรชั่นมีวิธีการใชงานที่แตกตางกัน จึงไมขอลงรายละเอียด

C:\> pathPATH=C:\WINNT\system32;C:\WINNT;C:\

C:\> set path=C:\WINNT\system32;C:\WINNT;C:\;C:\java\bin

C:\> pathPATH=C:\WINNT\system32;C:\WINNT;C:\;C:\java\bin

Page 15: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 2 จาวาเวอรชัวนแมทชีน และจาวาคอมไพลเลอร

15

จาวาโปรแกรมแรกของคุณเพ่ือทดสอบวาการติดต้ังเสร็จสมบูรณหรือไม เราจะทดลองเขียนโปรแกรมภาษาจาวาส้ัน ๆโปรแกรมหนึ่ง แลวทดลองคอมไพลและรันบนจาวาเวอรชัวนแมทชีน โปรแกรมที่วานี้มีชื่อวา HelloWorld ซึ่งไมทําอะไรมากนอกจาก แสดงขอความวา Hello World ออกท่ีหนาจอดอส

เรียกโปรแกรม Notepad แลวพิมพขอความนี้ลงไปโดยไมตองสนใจวาเนื้อหา (เราจะยังไมเรียนเร่ืองโครงสรางภาษาจาวาในบทนี้) สําหรับคนที่ใชระบบปฏิบัติการอื่นใหเรียกโปรแกรมสําหรับสรางเท็กซไฟลบนระบบปฏิบัติการน้ัน ๆขึ้นมา ตัวอยางเชน vi บนยูนิกซ

โปรแกรมที่ โปรแกรมที่ โปรแกรมที่ โปรแกรมที่ 2 2 2 2 –––– 1 1 1 1 : : : : HelloWorld.javaHelloWorld.javaHelloWorld.javaHelloWorld.java

public class HelloWorld {public static void main ( String [] args ) {

System.out.println ( “Hello World” ) ;}

}

พยายามพิมพใหเหมือนที่สุด โดยเฉพาะอยางยิ่งตัวอักษรพิมพเล็กพิมพใหญ และการเวนวรรคตอน เวลายอหนาคุณอาจใชแท็บก็ได จากน้ันทําการบันทึกไฟลน้ีลงบนท่ีไหนก็ไดในฮารดดิสก ขอแนะนําใหบันทึกลงบน C:\ และ ตั้งชื่อไฟลวา HelloWorld.java ระวังเรื่องตัวพิมพเล็กพิมพใหญของชื่อไฟล

รูปที่ รูปที่ รูปที่ รูปที่ 2222----4444 เขียนโปรแกรม เขียนโปรแกรม เขียนโปรแกรม เขียนโปรแกรม HelloWorld.java HelloWorld.java HelloWorld.java HelloWorld.java ดวย ดวย ดวย ดวย NotepadNotepadNotepadNotepad

ไฟลไฟลน้ีก็คือซอรสโคดภาษาจาวาท่ีเคยกลาวถึงในบทท่ีแลวน้ันเอง สิ่งที่พิมพลงไปในไฟลก็คือคําสั่งภาษาจาวา ซ่ึงในตอนนี้เรายังไมสนใจวาคําสั่งเหลานี้มีความหมายวาอยางไรบาง ไฟลซอรสโคดภาษาจาวามีตองจะนามสกุล .java เสมอ เมื่อเราไดโปรแกรมภาษาจาวาที่ชื่อ HelloWorld.java แลว เราจะลองทําการคอมไพล ดวยการเรียกหนาจอดอสออกมาแลวไปท่ี C:\ จากนั้นทดลองตรวจสอบดูวามีไฟลชื่อ HelloWorld.java อยูหรือไมดวยการพิมพคําสั่งดังในภาพ

Page 16: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 2 จาวาเวอรชัวนแมทชีน และจาวาคอมไพลเลอร

16

รูปที่ รูปที่ รูปที่ รูปที่ 2222----5555 ครวจสอบไฟล ครวจสอบไฟล ครวจสอบไฟล ครวจสอบไฟล HelloWorld.javaHelloWorld.javaHelloWorld.javaHelloWorld.java

เราเรียกคอมไพลเลอรใน SDK ขึ้นมาใชงานดวยการใชคําสั่ง javac คําส่ังน้ีจะถูกเรียกจากท่ีไหนก็ไดเพราะเราไดบอกระบบปฏิบัติการไปแลววาใหคอมไพลเลอรอยูที่ไหนดวยการเซตตัวแปร path ของระบบ ที่สําคัญคือที่ที่เรียกคําส่ัง javac ตองมีซอรสโคดของเราอยู ซ่ึงในกรณีน้ีซอรสโคดอยูท่ี C:\ เราจึงเรียกคําส่ัง javac จาก C:\ คําส่ัง javac จะตามดวยชื่อซอรสโคด ดังน้ี

ถาดอสไมฟองความผิดพลาดใด ๆออกมา แสดงวาคุณติดต้ัง SDK ไดอยางถูกตอง แตถามีขอความเกิดขึ้นแสดงวาเกิดความผิดพลาดข้ึน ซ่ึงสาเหตุอาจเกิดจากการติดต้ัง SDK ที่ยังไมถูกตอง หรืออาจเกิดคําสั่งภาษาจาวาที่คุณพิมพลงไปไมถูกตอง ขอใหยอนกับไปตรวจสอบทั้งสองกรณีและแกไขจนกวาดอสจะไมฟองความผดิพลาดใด ๆออกมา

ถาทุกอยางเรียบรอยใหตรวจสอบดูจะพบวาเกิดไฟลใหมขึ้นชื่อ HelloWorld.class ไฟลนี้คือโปรแกรมภาษาจาวาที่คอมไพลเสร็จแลว และพรอมที่จะใชงานได โปรแกรมภาษาจาวาที่คอมไพลแลวจะมีนามสกุล .class เสมอ และเปนไบนารีไฟลคือถาคุณลองเปดไฟลเหลาน้ีดูดวย Notepad คุณจะพบวาเนื้อความขางในไมใชภาษามนุษย อานไมรูเร่ือง มันเปนภาษาท่ีเราเรียกวา จาวาไบตโคด ซึ่งจาวาเวอรชัวนแมทชีนเทานั้นที่เขาใจ

เคล็ดลับ ถาตองการใชโปรแกรมชวยเขียนโปรแกรม เชน มีการนับบรรทัดของซอรสโคดให มีการใชสีของตัวอักษรในการแยกความแตกตางระหวางคําสั่งแตละประเภท หรือมีระบบตรวจสอบความผิดพลาดของโปรแกรมแบบทีละบรรทัด คุณอาจหันไปใชโปรแกรมประเภท IDE ตัวอยางเชน Borland JBuilder, WebGain VisualCafe,

Oracle JDeveloper, MetroWerks Code Warriors, Forte for Java ฯลฯ แทนการใช Notepad

C:\> javac HelloWorld.java

Page 17: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 2 จาวาเวอรชัวนแมทชีน และจาวาคอมไพลเลอร

17

คําส่ัง sourcepath

ถาคุณตองการเรียกคอมไพลเลอรจากโฟลเดอรอ่ืนท่ีไมใชโฟลเดอรที่มีไฟล .java ของคุณอยู คุณสามารถบอกตําแหนงที่เก็บไฟล .java ของคุณไดดวยคําส่ัง sourcepath ตัวอยางเชน เรารูวาตอนน้ีไฟล HelloWorld.java อยูที่ C: ใหเราลองเรียกคําส่ัง javac จากที่อื่น เชน C:\java ดังน้ี

คุณจะพบวาไมสามารถคอมไพลได เพราะคอมไพลเลอรจะหาตัวโปรแกรมไมเจอ คราวนี้ลองสั่งใหมดัวยคําสั่งดังตอไปน้ี

คราวนี้จะพบวาสามารถคอมไพลไดตามปกติ ถาลองตรวจสอบดูจะพบไฟล HelloWorld.class ในโฟลเดอร C:\java คําส่ัง sourcepath อยูตอทายคําส่ัง javac และมีเครื่องหมาย – นําหนา และตามดวยชื่อโฟลเตอรที่เปนที่อยูของไฟล .java สวนช่ือไฟลอยูทายสุดเสมอ

แมวาเราจะสามารถรันคําส่ัง javac จากที่ไหนก็ได เพราะเราสามารถใชคําส่ัง sourcepath ในการระบุตําแหนงของไฟล .java แตเพื่อความสะดวกในการอางอิงของใหคุณเก็บไฟล .java ใด ๆก็ตามที่คุณเขียนขึ้นไวในโฟลเดอร C:\java และคอมไพลในโฟลเดอรน้ีตลอดเน้ือหาในหนังสือเลมน้ี

และขอแนะนําใหคุณลองพิมพโปรแกรมตัวอยางทุกโปรแกรมในหนังสือดวยตัวเอง บันทึก คอมไพล และรัน ดูวาใชงานไดจริงหรือไมทุกโปรแกรม การพิมพโปรแกรมตัวอยางเองทีละบรรทัดอาจเสียเวลาแตจะทําใหเกิดความคุนเคยและเขาใจอยางถองแท

ตอนนี้ใหคุณยายไฟล HelloWorld.java ของคุณเขามาในโฟลเดอร C:\java ดังน้ี

C:\> cd javaC:\java> javac HelloWorld.java

C:\java> javac –sourcepath C:\ HelloWorld.java

C:\java> copy C:\HelloWorld.java C:\javaC:\java> del C:\HelloWorld.javaC:\java> del C:\HelloWorld.class

Page 18: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 2 จาวาเวอรชัวนแมทชีน และจาวาคอมไพลเลอร

18

ลองรันโปรแกรม HelloWorldเมื่อเราไดโปรแกรมภาษาจาวาที่คอมไพลแลว ซ่ึงก็คือไฟล HelloWorld.class เวลาจะรันตองรันดวยจาวาเวอรชัวนแมทชีน เราเรียกจาวาเวอรชัวนแมทชีนไดดวยคําสั่ง java ตามดวยชื่อของโปรแกรมภาษาจาวาที่ตองการจะรัน ดังน้ี

โปรดสังเกตวาเวลาเรียกคําส่ัง จาวา ชื่อของโปรแกรมที่ตามมาจะไมมีนามสกุล .class ตอทาย ทั้ง ๆที่โปรแกรมภาษาจาวาคือไฟลนามสกุล .class ตางกับกรณีของการเรียกคําส่ัง javac ที่ตองมีนามสกุล .java ตอทายชื่อไฟลโปรแกรมเสมอ

ผลลัพธท่ีไดจากการรันโปรแกรม HelloWorld.class ก็คือ โปรแกรมจะพิมพคําวา Hello World ออกมาท่ีหนาจอดังภาพ

คําส่ัง java ตองเรียกในโฟลเดอรเดียวกันกับโฟลเดอรท่ีมีไฟลนามสกุล .class ท่ีเราจะรันอยู

ถาทุกอยางเรียบรอย แสดงวาการติดต้ัง SDK สมบูรณแบบ และคุณก็ไดเขียนและรันโปรแกรมจาวาโปรแกรมแรกในชีวิตของคุณเสร็จเรียบรอยแลว

ถาคุณมีเคร่ืองคอมพิวเตอรท่ีรันระบบปฏิบัติการอ่ืน คุณสามารถนําไฟล HelloWorld.class ของคุณไปทดลองรันบนระบบปฏิบัติการน้ัน ๆได ขอใหมีจาวาเวอรชัวนแมทชีนอยู โปรแกรมภาษาจาวาสามารถรันไดทุกระบบปฏิบัติการโดยไมตองมีการแกไขอะไรเลย

C:\java> java HelloWorld

C:\java> java HelloWorldHello World

C:\java>

Page 19: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

3 โปรแกรม Hello World

ในบทนี้เรามาวิเคราะหสิ่งที่อยูภายในไฟล HelloWorld.java กัน

อยางที่เคยบอกไปแลว จาวา เปนภาษาเชิงวัตถุ ซอรสโคดของโปรแกรมภาษาเชิงวัตถุประกอบดวยนิยามของวัตถุหลาย ๆวัตถุเขียนเรียงตอกันไปเรื่อย ๆ นิยามของวัตถุในภาษาจาวาเราเรียกวา คลาส

โปรแกรม HelloWorld มีเนื้อหาดังตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 3 3 3 3 ---- 1 1 1 1 : HelloWorld.java: HelloWorld.java: HelloWorld.java: HelloWorld.java

public class HelloWorld {public static void main (String [] args) {

System.out.println (“Hello World”);}

}

โปรแกรมนี้มีคลาสแคหนึ่งคลาส เพราะเปนโปรแกรมงาย ๆ สังเกตคําส่ัง class ในบรรทัดแรกสุด ชื่อของคลาสคลาสน้ีคือคําส่ังท่ีอยูตามมาไดแกคําวา HelloWorld นั้นคือคลาสนี้มีชื่อเหมือนกับชื่อโปรแกรมและชื่อไฟลดวย ตัวพิมพเล็กพิมพใหญมีความสําคัญมากในภาษาจาวา ชื่อ HELLOWORLD ,Helloworld, helloworld และ

Page 20: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 3 โปรแกรม Hello World

20

HelloWorld ถือวาไมเหมือนกัน โปรแกรมท่ีมีคลาสแคคลาสเดียว คลาสน้ันตองมีช่ือเหมือนกับช่ือไฟลเสมอ และตองมีคําวา public นําหนาคําส่ัง class ตอนนี้ยังไมตองสนใจวาทําไมตองมีคําวา public

ช่ือคลาสตองเปนคํา ๆเดียว ดังน้ันเราจึงต้ังช่ือคลาสวา HelloWorld แทนที่จะเปน Hello World

ถดไปจากคําวา HelloWorld คือ เครื่องหมายวงเล็บปกกาเปด ถาคําวา public class HelloWorld

ซึ่งอยูหนาเครื่องหมายวงเล็บปกกาเปดเรียกวา สวนหัวของคลาส HelloWorld สิ่งที่อยูระหวางวงเล็บปกกาเปดอันแรกสุด กับวงเล็บปกกาเปดอันสุดทายของไฟลคือ สวนตัวของคลาส HelloWorld

เน้ือความของคลาส HelloWorld ประกอบดวยแมธธอสหนึ่งแมธธอส ชื่อวา main คําวา แมธธอส หมายถึงสิ่งที่บรรจุคําสั่งที่บอกใหโปรแกรมทําอะไรตอมิอะไร สังเกตคําวา main ในบรรทัดท่ีสอง นั้นคือตําแหนงของชื่อแมธธอส โปรแกรมทุกโปรแกรมในภาษาจาวาตองมีแมธธอสหนึ่งแมธธอสที่มีชื่อวา main เสมอ

ยังไมตองสนใจคําส่ัง public static void ที่มากอนคําวา main และคําส่ัง (String [] args) ที่ตามหลังมา ขอใหเขาใจวาทั้งหมดคือ สวนหัวของแมธธอส ขอใหสังเกตวงเล็บกามปูเปดที่อยูทายบรรทัดที่สอง ขอความทั้งหมดที่อยูระหวางวงเล็บกามปูเปดนี้กับวงเล็บกามปูปดในบรรทัดรองสุดทายคือ สวนตัวของแมธธอส

จะเห็นไดท้ังคลาสและแมธธอสมีโครงสรางคลายกันและซอนกันอยู คือประกอบดวยสวนหัวซึ่งมีชื่อของคลาสหรือแมธธอสอยู และสวนเนื้อความซึ่งอยูในวงเล็บกามปูที่ตามมา แตเรานิยมวางวงเล็มกามปูเปดไวทายสวนหัวของคลาสหรือแมธธอส และวางวงเล็บกามปูปดไวโดดเดี่ยวในบรรทัดสุดหลังจบเนื้อความโดยยอหนาใหตรงกับสวนหัว สวนเนื้อความจะอยูในบรรทัดระหวางวงเล็บกามปูเปดและวงเล็บกามปูปด โดยยอหนาเขาไปหนึ่งระดับใหลึกกวาสวนหัวทุกบรรทัด ทั้งหมดนี้เปนเพียงความนิยมในการเขียนโปรแกรมใหดูงายสะอาดตาเทาน้ัน การเวนบรรทัดในภาษาจาวาไมมีความหมายใด ๆท้ังส้ิน โปรแกรม HelloWorld อาจเขียนติด ๆกันเปนแบบน้ีก็ได

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 3 3 3 3 ---- 2 2 2 2 : HelloWorld.java: HelloWorld.java: HelloWorld.java: HelloWorld.java

public class HelloWorld {public static void main (String[] args){System.out.println (“Hello World”); } }

แตไมนิยมเพราะอานยาก

เคล็ดลับ ไมมีกฎแนนอนตายตัววาคุณควรเวนบรรทัดเมื่อไหร ทั้งหมดขึ้นอยูกับวิจารณญาณของคุณเอง จุดมุงหมายของการเวนบรรทัดคือการทําใหโปรแกรมอานงาย การยอหนาคุณอาจใชเครื่องหมายแท็บก็ได แตวิธีการที่ดีกวาคือการเวนวรรคธรรมดา เพราะเคร่ืองหมายแท็บอาจมีปญหาเวลาใชงานขามระบบปฏิบัติการ และการเวนวรรคท่ีนิยมท่ีสุดเวลาใชแทนการยอหนาคือการเวนสองชองไฟ (เคาะ Space สองที)

Page 21: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 3 โปรแกรม Hello World

21

ระหวางคําทุกคําในโปรแกรมภาษาจาวาคุณจะเวนวรรคดวยการเคาะ Space กี่ครั้งก็ไดตั้งแตหนึ่งครั้งเปนตนไป ยกเวนเมื่อระหวางคํามีเครื่องหมายคั้นกลางอยู เชน . ( ) { } [ ] ; เราอาจไมตองเวนวรรคเลยก็ได เพราะจาวาจะถือวาคําที่อยูหนาเครื่องหมายเปนคนละคํากับคําที่อยูหลังเครื่องหมายโดยอัติโนมัติ เชน

public static void main() (String args[]) {public static void main ( ) ( String args [ ] ) {

public static void main( ){String args[ ]){public static void main()(String args[]){

ทุกบรรทัดขางตนไมแตกตางกัน

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

System.out.println (“Hello World”);

ก็คือคําสั่งใหโปรแกรมพิมพคําวา Hello World ออกหนาจอน้ันเอง

ถาเราใสคําส่ังน้ีเขาไปในเน้ือความสองคําส่ัง คุณคงเดาไดวาจะเกิดอะไรข้ึน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 3 3 3 3 ---- 3 3 3 3 : HelloWorld.java: HelloWorld.java: HelloWorld.java: HelloWorld.java

public class HelloWorld {public static void main (String [] args) {

System.out.println (“Hello World”);System.out.println (“Hello World”);

}}

ลองสรางโปรแกรมน้ีดวย Notepad ดู ลองเรียก Notepad จากดอส ดังน้ี

คําส่ังน้ีเรียก Notepad ออกมาเพ่ือสรางเท็กซไฟลช่ือ HelloWorld.java คุณควรพบเนื้อหาของโปรแกรม HelloWorld อันเกาคางอยูในไฟล แกไขเพิ่มเติมดวยการตอเติมใหเหมือนโปรแกรม 3-3 แลวบันทึก จากน้ันลองคอมไพลโปรแกรมดู ดังน้ี

C:\java> notepad HelloWorld.java

C:\java> javac HelloWorld.java

Page 22: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 3 โปรแกรม Hello World

22

รันโปรแกรมดูโดยการเรียกจาวาเวอรชัวนแมทชีนจะไดผลดังนี้

ถาตองการใหโปรแกรมเขียนคําวา Hello World สิบคร้ัง ก็ใสสิบคําส่ัง ประเด็นอยูวาคําส่ังท่ีเราตองการใหโปรแกรมทํางานจะอยูในเนื้อความของแมธธอส main โดยเขียนเรียงตอไปเรื่อย ๆ คําสั่งในภาษาจาวาทุกคําสั่งจะจบดวยเครื่องหมาย ; เพ่ือเปนการบอกวาส้ินสุดคําส่ังแลว จาวาคอมไพลเลอรจะใชเครื่องหมายนี้ในการแบงแยกคําส่ังท่ีมากอน กับคําส่ังท่ีอยูถัดไป แทนที่จะดูจากการเวนบรรทัด แตอยางไรก็ดีเรานิยมเวนบรรทัดระหวางคําสั่งดวย เพื่อใหอานงาย

ลองดูคําส่ังท่ีใหเขียนออกหนาจออีกคร้ัง สังเกตใหดีตรงคําวา Hello World

System.out.println (“Hello World”);

คุณคงเดาออกวา ถาเราตองการใหโปรแกรมเขียนขอความอะไร ก็ใหใสขอความนั้นลงไปแทนที่คําวา HelloWorld ในตําแหนงเดียวกัน ซ่ึงเปนการเดาท่ีถูกตอง ขอใหจําไววาเราสามารถสั่งใหโปรแกรมของเราเขียนคําวาอะไรก็ไดออกหนาจอดวยการใชคําสั่งขางตน

โปรแกรม Hello World เปนโปรแกรมงาย ๆส้ัน ๆ แตเมื่อคุณตองเขียนโปรแกรมที่ใหญ และซบซอน โปรแกรมของคุณอาจมีเปนสิบ ๆคลาส รอย ๆ แมธธอส พัน ๆบรรทัด ซ่ึงยากตอการอาน โดยเฉพาะอยางยิ่งเมื่อเวลาที่คอมไพลไมผานและตองการหาที่ผิด ดังน้ัน บางทีคุณอาจตองการเขียนโนตอธิบายสวนตาง ๆของโปรแกรมเล็กนอย ๆตามตําแหนงตาง ๆในโปรแกรมภาษาจาวาของคุณ เพราะใหเวลาท่ีคุณกลับมาดูโปรแกรมของคุณอีกคร้ัง คุณจะเขาใจไดรวดเร็วขึ้น การเขียนขอความใด ๆนอกเหนือจากคําส่ังภาษาจาวาสามารถทําไดสองวิธี

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

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 3 3 3 3 ---- 4 4 4 4 : HelloWorld.javaHelloWorld.javaHelloWorld.javaHelloWorld.java

/* HelloWorldWritten by NarinSince December 16, 2001All rights reserved

*/

C:\java> java HelloWorldHello WorldHello World

Page 23: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 3 โปรแกรม Hello World

23

public class HelloWorld{public static void main(String[]args){

System.out.println(“Hello World”);}

}

/* End of program*/

สังเกตวาขอความที่อยูขางในจะยาวกี่บรรทัดก็ได และจะอยูที่ไหนก็ไดในโปรแกรมของคุณ

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

โปรโปรโปรโปรแกรม แกรม แกรม แกรม 3 3 3 3 ---- 5 5 5 5 : HelloWorld.java: HelloWorld.java: HelloWorld.java: HelloWorld.java

public class HelloWorld{public static void main(String[]args){

System.out.println(“Hello World”); // Echo Hello World}

}

Page 24: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

4 คาคงตัว และ ตัวแปรพื้นฐาน

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

คนที่เขียนโปรแกรมภาษาโครงสรางมีพอสมควร คงจะรูสึกวาเน้ือหาในบทน้ีเปนเร่ืองงาย ๆ คุณสามารถอานผาน ๆไปไดอยางรวดเร็ว แตไมขอแนะนําใหขามไปเลย เพราะภาษาจาวามรีายละเอียดปลีกยอยท่ีไมเหมือนภาษาอ่ืน และในบทน้ีเราจะเนนขอแตกตางเหลาน้ันเปนหลัก

คาคงตัวคาคงตัว คือ ขอมูลที่เราปอนใหกับคอมพิวเตอร เพื่อใหคอมพิวเตอรนําไปใชในการคํานวนตามที่เราตองการ คาคงตัวในภาษาจาวามี 5 ชนิดหลัก ๆ ไดแก คาคงตัวจํานวนเต็ม คาคงตัวทศนิยม คาคงตัวตรรก คาคงตัวตัวอักษร และ คาคงตัวขอความ แตละชนิดมีรูปแบบการเขียนที่เฉพาะเจาะจง

Page 25: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 4 คาคงตัวและตัวแปรพ้ืนฐาน

25

คาคงตัวจํานวนเต็มคาคงตัวชนิดแรกคือจํานวนเต็ม จํานวนเต็มในภาษาจาวามีสองแบบคือ คาคงตัวจํานวนเต็มปกติ และคาคงตัวจํานวนเต็มแบบยาว

รูปแบบการเขียนคาคงตัวจํานวนเต็มปกติ เราใชตัวเลขจํานวนเต็มธรรมดา เชน 13, 200, -10, 12541

คาคงตัวจํานวนเต็มปกติเปนไดทั้งคาบวกและลบ และมีคาไดระหวาง –214783648 ถึง +2147483647 ถาตองการเขียนเลขจํานวนเต็มที่มีคามากกวานี้ ตองใชคาคงตัวจํานวนเต็มอีกแบบหนึ่งคือ คาคงตัวจํานวนเต็มแบบยาว

รูปแบบการเขียนคาคงตัวจํานวนเต็มแบบยาว เราใชตัวเลขจํานวนเต็มตอทายดวยอักษร L หรือ l เชน13L, 200L, -10L, 12541L, 50000000000L

คาคงตัวจํานวนเต็มแบบยาวมีคาไดระหวาง -9223372036854775808 ถึง 9223372036854775807

สําหรับคนท่ีคุนเคยกับเลขฐานสอง เลขฐานแปด และเลขฐานสิบหก เราสามารถเขียนคาคงตัวจํานวนเต็มเปนเลขฐานไดดวย รูปแบบของการเขียนก็คือใชสัญลักษณ 0 นําหนาถาเปนเลขฐานแปด และใชสัญลักษณ 0x นําหนาถาเปนเลขฐานสิบหก ตัวอยางเชน ตัวเลข 27 ในฐานสิบ มีคาเทากับ 33 และ 1B ในฐานแปดและสิบหกตามลําดับ เราอาจเขียนเปน 033 หรือ 0x1b ก็ได

คาคงตัวทศนิยมคาคงตัวทศนิยมในภาษาจาวามีสองแบบคือ คาคงตัวทศนิยมปกติ และคาคงตัวทศนิยมแบบยาว

ตัวเลขทศนิยมจะตองมีจุดเสมอแมวาจะทศนิยมตัวนั้นจะมีคาเทากับจาํนวนเต็ม เชน 5 ตองเขียนวา 5.0 เพราะจาวาจะใชจุดในการแยกแยะระหวางทศนิยมกับจํานวนเต็ม

รูปแบบการเขียนคาคงตัวทศนิยมปกติ เราใชตัวเลขทศนิยมธรรมดาตามดวยอักษร F หรือ f เชน 10.2F, 21501.45F, 5.0F, 3152.34F

คาคงตัวทศนิยมปกติเปนไดตั้งแต –1.4x1045 และ +3.4x1038 ถาตองการเขียนทศนิยมมีคามากกวานี้ ตองใชคาคงตัวจํานวนเต็มอีกแบบหนึ่งคือ คาคงตัวทศนิยมแบบยาว

รูปแบบการเขียนคาคงตัวทศนิยมแบบยาว เราใชเลขทศนิยมตอทายดวยอักษร D หรือ d หรือจะเขียนเลขทศนิยมเฉย ๆก็ได เชน10.2D, 21501.45D, 5.0D, 5.0, 3152.34

คาคงตัวทศนิยมมีคาไดตั้งแต -4.9 x 10-324 ถึง1.7 x 10308

Page 26: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 4 คาคงตัวและตัวแปรพ้ืนฐาน

26

เราสามารถเขียนตัวเลขทศนิยมใหอยูในรูปของเลขยกกําลังไดดวย โดยเราใชสัญลักษณ e เชน 1.7e308 หมายถึง 1.7x 10308

คาคงตัวตรรกคาคงตัวตรรก คือคาความจริงทางตรรกศาสตร ซ่ึงเปนไปไดแคสองกรณีเทาน้ัน คือ จริง หรือ เท็จ เราใชคําเฉพาะวา true และ false ตามลําดับ ตัวอยางเชน

true, false

ทั้งสองคําตองเขียนดวยอักษรตัวพิมพเล็กเทานั้น

คาคงตัวตัวอักษรคาคงตัวตัวอักษร ไดแกตัวอักษร ตัวเลข เครื่องหมาย และสัญลักษณตาง ๆ เราใชเครื่องอัญประกาศขาเดียวลอมตัวอักษรน้ันเวลาเขียน ตัวอยางเชน ‘a’, ‘A’, ‘z’, ‘Z’, ‘0’, ‘9’ , ‘$’

มีเครื่องหมายบางตัวเวลาเขียนตองใสเครื่องหมาย \ไวขางหนาตัว เครื่องหมายในกลุมนี้มีหลายตัวแตที่ควรจดจํา ไดแก

ตารางที่ตารางที่ตารางที่ตารางที่ 4444----1111 เครื่องหมายพิเศษและวิธีการเขียนใหอยูในรูปของคาคงตัวตัวอักษรเครื่องหมายพิเศษและวิธีการเขียนใหอยูในรูปของคาคงตัวตัวอักษรเครื่องหมายพิเศษและวิธีการเขียนใหอยูในรูปของคาคงตัวตัวอักษรเครื่องหมายพิเศษและวิธีการเขียนใหอยูในรูปของคาคงตัวตัวอักษร

ตัวอักษร วิธีเขียนโดยใชเครื่องหมายอัญประกาศ

Backspace ‘\b’ Horizontal tab ‘\t’

Linefeed ‘\n’ Form feed ‘\f’

Carriage return ‘\r’ Apostrophe-quote ‘\’’

Quotation mark ‘\’’’ Backslash ‘\\’

คาที่เปนไปไดของคาคงตัวตัวอักษรไมไดมีแคอักษรที่เห็นบนแปมพิมพเทานั้น แตเปนอักขระอะไรก็ไดท่ีอยูในรหัสยูนิโคด 16 บิตสากล อักขระเหลาน้ีจะมีรหัสประจําตัวอยูเปนเลข 16 บิต ตัวอยางของอักขระบางสวนของรหัสยูนิโคด 16 บิตสากล และรหัสประจําตัวเปนดังน้ี

ตารางที่ตารางที่ตารางที่ตารางที่ 4444----2222 บางสวนของอักขระในรหัสยูนิโคด บางสวนของอักขระในรหัสยูนิโคด บางสวนของอักขระในรหัสยูนิโคด บางสวนของอักขระในรหัสยูนิโคด 16 16 16 16 บิต พรอม รหัสประจําตัวบิต พรอม รหัสประจําตัวบิต พรอม รหัสประจําตัวบิต พรอม รหัสประจําตัว

ตัวอักษร วิธีการเขียนโดยใชเลขฐานสิบหกประจํารหัสยูนิโคด

Page 27: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 4 คาคงตัวและตัวแปรพ้ืนฐาน

27

0 0030 9 0039 a 0061 A 0041 z 007a Z 005a ả 008c ß 00a7

อักขระเหลานี้บางตัวไมมีอยูบนแปนพิมพ ดังน้ัน จาวาจึงยอมใหเราเขียนคาคงตัวตัวอักขระในรูปของเลข 16 บิตประจําตัวของมันไดดวย โดยตองเขียนคําวา \u นําหนาเชน ‘a’ อาจเขียเปน \u0061 ก็ได

คาคงตัวขอความคาคงตัวขอความ มีลักษณะคลายคาคงตัวแบบตัวอักษรแตมีความยาวไดมากกวาหนี่งตัวอักษรและใชเครื่องหมายอัญประกาศสองขาครอมขอความไว ตวอยางเชน

“Hello World” , “This is the message.”, “a”

เราสามารถผสมรหัสยูนิโคดหรือ escape character ไดเชนเดียวกับคาคงตัวอักษร ตัวอยางเชน

“I said \”yes.\””

หมายถึง ขอความ I said “yes.”

“Here comes a tab. \t And here comes another one \u0009”

หมายถึง ขอความ Here comes a tab.[tab]And here comes another one [tab]

ตัวแปรตัวแปร คือหนวยความจําในแรม ซึ่งสามารถใชเก็บคาคงตัวได ตัวแปรพื้นฐานในภาษาจาวามี 8 ชนิดไดแก ตัวแปรจํานวนเต็ม ตัวแปรทศนิยม ตัวแปรตรรก และ ตัวแปรตัวอักษร

ตัวแปรจํานวนเต็มตัวแปรจํานวนเต็มมีสี่ชนิดคือ byte, short, int และ long แตละชนิดมีขนาดไมเทากัน ขนาดของตัวแปรนับเปนไบต ซึ่งก็คือขนาดของหนวยความจํานั้นเอง ตัวแปรจํานวนเต็มขนาดเล็กใชเก็บคาไดไมใหญเทาตัวแปรจํานวนเต็มขนาดใหญ แตกินเนื้อที่ในแรมนอยกวา

Page 28: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 4 คาคงตัวและตัวแปรพ้ืนฐาน

28

คาสูงสุด ต่ําสุดที่ตัวแปรแตละชนิดเก็บได และขนาดในแรม สรุปไดดังตาราง

ตารางที่ตารางที่ตารางที่ตารางที่ 4444--------3333 ตัวแปรจํานวนเต็มตัวแปรจํานวนเต็มตัวแปรจํานวนเต็มตัวแปรจํานวนเต็ม

ชื่อชนิดของตัวแปร

คาสูงสุด คาต่ําสุด ขนาดในแรม

byte +127 -128 1 ไบต short +32767 -32768 2 ไบต

int +2147483647 -214783648 4 ไบต long 9223372036854775807 -9223372036854775808 8 ไบต

ตัวแปรทศนิยมตัวแปรทศนิยมมีสองชนิดคือ float และ double คาสูงสุด ต่ําสุดที่ตัวแปรแตละชนิดเก็บได และขนาดในแรม สรุปไดดังตาราง

ตารางที่ ตารางที่ ตารางที่ ตารางที่ 4444 ---- 4444 ตัวแปรทศนิยมตัวแปรทศนิยมตัวแปรทศนิยมตัวแปรทศนิยม

ชื่อชนิดของตัวแปร

คาสูงสุด คาต่ําสุด กินเน้ือท่ีแรม

float 3.40282 x 1038 -1.4 x 10-45 4 ไบต double 1.79769 x 10308 -4.9 x 10-324 8 ไบต

ตัวแปรตรรกตัวแปรตรรกใชเก็บคาความจริงทางตรรกศาสตรมีชนิดเดียวคือ boolean

ตัวแปรตัวอักษรตัวแปรตัวอักษรใชเก็บตัวอักษรมีชนิดเดียวคือ char และมีขนาด 2 ไบต

ชื่อของตัวแปรเพื่อใหเราสามารถอางอิงถึงตัวแปรที่เราบอกใหจาวาเวอรชัวนแมทชนีสรางข้ึนไดตลอดโปรแกรมท่ีเราเขียนข้ึน เราตองมีการตั้งชื่อใหกับตัวแปร การตั้งชื่อตัวแปรนั้นจะใชชื่ออะไรก็ได ตัวอักษรที่ประกอบเปนชื่อจะเปนตัวอักษรภาษาอังกฤษตัวพิมพเล็ก ตัวพิมพใหญ ตัวเลข เคร่ืองหมายสกุลเงินตาง ๆ อักษรโรมนั รวมทั้งเครื่องหมาย _

มีขอแมคือชื่อของตัวแปรหามขึ้นตนดวยตัวเลข และตัวพิมพโหญกับตัวพิมพเล็กถือวาเปนคนละตัวอักษร นอกจากน้ียังหามตั้งชื่อดวยคําสงวน ซึ่งมีดังตอไปนี้

abstract do import public throws

Page 29: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 4 คาคงตัวและตัวแปรพ้ืนฐาน

29

boolean double instanceof return transientbreak else int short trybyte extends interface static voidcase final long strictfp volatilecatch finally native super whilechar float new switch nullclass for package synchronized truecontinue if private this falsedefault implements protected throw

ตัวอยางตอไปนี้เปนชื่อตัวแปรที่ถูกหลักภาษาจาวา

number, Number, sum_$, $_100

ตอไปนี้เปนตัวอยางชื่อตัวแปรที่ไมถูกหลักภาษาจาวา

4Thai, all/done, get-big-fast

กฏการตั้งชื่อของตัวแปรนี้นําไปใชในการตั้งชื่อคลาสและแมธธอสไดดวย

ชื่อตัวแปรในภาษาจาวานิยมใชชื่อที่ขึ้นตนดวยอักษรภาษาอังกฤษตัวพิมพเล็ก และถาประกอบดวยคําหลาย ๆคําจะใชตัวพิมพใหญขึ้นตนคําทุกคําที่ตามมาเชน

x, anInt, getBigFast

ทั้งนี้เปนเพียงแคความนิยมเทานั้น

เมื่อเราไดชื่อของตัวแปรที่เราตองการจะสรางแลว คําสั่งที่ใชในการสรางตัวแปรมีสองขั้นตอน คือคําส่ังในการประกาศตัวแปร และคําสั่งในการกําหนดคาคงตัวใหกับตัวแปร

การประกาศตัวแปรเราสามารถบอกใหจาวาเวอรชัวนแมทชีนจองที่ในแรมใหเราเพื่อไวใชเปนตัวแปรเก็บคาคงตัวไดดวยการประกาศตัวแปร รูปแบบของคําสั่งในการประกาศตัวแปรเปนดังตัวอยาง

int anInt;byte aByte;long l;short aShort;char c;float f;boolean oasis;

Page 30: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 4 คาคงตัวและตัวแปรพ้ืนฐาน

30

นั้นคือเราประกาศตัวแปรไดดวยการใชชื่อของชนิดของตัวแปร ตามดวยชื่อของตัวแปรซึ่งเปนชื่ออะไรก็ไดที่เราตั้งขึ้นเอง คําสั่งนี้เปนการบอกใหจาวาเวอรชัวนแมทชีนจองเนื้อที่ไวใชเปนตัวแปรโดยขนาดของเนื้อที่จะขึ้นอยูกับชนิดของตัวแปรท่ีเราประกาศ อยาลืมเครื่องหมาย ; ท่ีบอกจุดส้ินสุดของคําส่ัง

ในกรณีท่ีตองการประกาศตัวแปรทีละหลาย ๆตัว สามารถทําไดในคําส่ังเดียว แตตัวแปรเหลานั้นตัองเปนตัวแปรชนิดเดียวกัน เชน

int i,j,k;

ตัวอยางนี้เปนการประกาศตัวแปร int จํานวนทั้งสิ้นสามตัวชื่อ i j และ k ตามลําดับ เราใชเครื่องหมายจุลภาคในการคั่นระหวางชื่อของตัวแปร

การกําหนดคาตัวแปรเมือ่เราประกาศตัวแปรแลว ขั้นตอนตอไปก็คือการกําหนดคาคงตัวใหกับตัวแปร ในขณะที่การประกาศตัวแปรเปนการบอกใหเวอรชัวนแมทชีนกันที่ในแรมไวให การกําหนดคาตัวแปรเปนการนําคาคงตัวมาใสไวในที่วางนั้น รูปแบบของคําสั่งในการกําหนดคาตัวแปรเปนดังตัวอยาง

anInt = 5;aByte = 15;l = 2000L;aShort = 129;c = ‘g’;f = 10.05F;oasis = true;

รูปแบบของคําสั่งกําหนดคาใหตัวแปร เริ่มจากชื่อของตัวแปร ตามดวยเครื่องหมายเทากับ และตามดวยคาคงตัวที่ตองการเก็บ ชนิดของตัวแปรและชนิดของคาคงตัวตองสัมพันธกัน ตัวอยางเชน ตัวแปร int ใชเก็บคาคงตัวจํานวนเต็ม จะกําหนดใหมีคาเทากับคาคงตัวตรรกไมได

ถาชนิดของตัวแปรและคาคงตัวที่กําหนดใหสอดคลองกัน แตขนาดของตัวแปรไมสามารถรับคาคงตัวได ก็ไมสามารถกําหนดคาใหได เชน ตัวแปร int ไมสามารถรับคาคงตัวจํานวนเต็ม 5000000000000L ไดเพราะใหญเกินพิสัยของมัน

เวลากําหนดตัวแปรจํานวนเต็ม ตัวแปร byte, short และ int จะรับคาคงตัวจํานวนเต็มปกติ สวนตัวแปร long จะรับคาคงตัวจํานวนเต็มปกติ หรือคาคงตัวจํานวนเต็มแบบยาวก็ได เชน

aByte = 5;aShort = 50;anInt = 500;l = 50000000000L;l = 5000;

Page 31: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 4 คาคงตัวและตัวแปรพ้ืนฐาน

31

anInt = 500L; // Error

ในกรณีสุดทาย แมตัวแปร int จะรับคาขนาด 500 ได แตเราเขียน 500 เปนแบบคาคงตัวจํานวนเต็มแบบยาว จาวาจะถือวามีขนาดใหญกวาตัวแปร int จึงใชตัวแปร int เก็บไมได

ตัวแปร short และ byte มีพิสัยแคบกวาตัวแปร int หามรับคาเกินพิสัย เชน aByte = 130; //Error

คําสั่งนี้ใชไมไดเพราะ ตัวแปร byte มีคาสูงสุดไดแค 127 เทาน้ัน

ตัวแปร char นอกจากจะกําหนดใหมีคาเปนตัวอักษรแลว ยังกําหนดใหมีคาเปนตัวเลขไดดวย เชน c = 97;

แตผลท่ีไดก็คือจะได c = ’a’ เพราะอักขระ a มีรหัสยูนิโคดประจําตัวเปน \u0061 ซ่ึงเทากับ 97 ในระบบเลขฐานสิบ หรืออีกนัยหนึ่งเราสามารถกําหนดคาใหตัวแปร c มีคาเทากับอักขระ a ไดสามแบบดังนี้

c = ‘a’;c = \u0061;c = 97;

เมื่อทราบวิธีประกาศและกําหนดคาของตัวแปรแลว เรามาลองเขียนโปรแกรมจริง ๆโดยใชคําสั่งเหลานี้ดู ลองเรียกดอสขึ้นมา แลวเรียก Notepad ในโฟลเดอร C:\java เพ่ือสรางเท็กซไฟลช่ือ TestVariable.java ดังน้ี

พิมพโปรแกรมตอไปนี้ลงไปแลวบันทึกไวใน C:\java ระวังไมใหมีนามสกุล .txt ตอทายเวลาบันทึก

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 4 4 4 4 ---- 1 1 1 1 : TestVariable.java: TestVariable.java: TestVariable.java: TestVariable.java

public class TestVariable {public static void main(String[]args){

int i; // (1)i = 20; // (2)System.out.println(i); // (3)i = 97; // (4)System.out.println(i); // (5)char c; // (6)c = i; // (7)System.out.println(c); // (8)

}}

C:\java> notepad TestVariable.java

Page 32: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 4 คาคงตัวและตัวแปรพ้ืนฐาน

32

คงยังจําไดวาโปรแกรมในภาษาจาวาประกอบดวยคลาส ในคลาสมีแมธธอส และถาเราตองการสั่งใหโปรแกรมทําอะไรตอมิอะไรเราก็เพียงแตใสคําสั่งเหลานั้นลงไปในสวนตัวของแมธธอส โปรแกรมขางตนก็เชนกัน ประกอบดวยคลาสหน่ึงคลาสช่ือ TestVariable ภายในมีแมธธอสชื่อ main สวนตัวของแมธธอส main มีคําส่ัง 8 คําส่ัง คําส่ังในบรรทัด (1) คือคําสั่งประกาศตัวแปรชนิด int ใหชื่อวา i

คําส่ังในบรรทัด (2) คือคําสั่งกําหนดคาตัวแปร i ใหเทากับ 20

คําส่ังในบรรทัด (3) คือคําสั่งใหแสดงคาของตัวแปร i ออกนอกจอ ซึ่งก็คือคาคงตัวที่ i เก็บไว ไดแก 20

คําส่ังในบรรทัด (4) กําหนดคาใหมให i มีคาเทากับ 97

คําส่ังในบรรทัด (5) แสดงคา i ออกนอกจอใหม คราวนี้มีคาเปน 97

คําส่ังในบรรทัด (6) เปนการประกาศตัวแปร char ใหชื่อวา c

คําส่ังในบรรทัด (7) กําหนดใหตัวแปร c มีคาเทากับคาของตัวแปร i ซ่ึงก็คือ 97

คําส่ังในบรรทัด (8) แสดงคา c ออกนอกจอ คราวน้ีจะไดเปน a ทดลองคอมไพลโปรแกรมน้ีและรันดู ดังน้ี

สิ่งที่ไดจากโปรแกรมนี้ก็คือ ตัวแปรเปนแคเนื้อที่วางในแรม ซ่ึงเราสามารถกําหนดคาใหใหมไดตลอดเวลา และเราสามารถกําหนดคาของตัวแปรใหมีคาเทากับคาของตัวแปรอื่นไดดวย

สังเกตวาคราวน้ีส่ิงท่ีอยูในวงเล็บหลังคําส่ัง System.out.println ไมมีเครื่องหมายคําพูดครอมอยู เคร่ืองหมายคําพูดเปนบงบอกลักษณะของคาคงตัวแบบขอความ แตครั้งนี้เราตองการแสดงคาตัวแปรไมใชขอความ ดังน้ันจึงเขียน i หรือ c เฉย ๆ ไมมีเครื่องหมายคําพูด ถาเราใสเคร่ืองหมายคําพูดครอม i หรือ c ส่ิงท่ีไดคือตัวอักษร i หรือ c ออกนอกจอ ไมใชคาของ i หรือ c ท่ีเราตองการ

อันที่จริงแมการประกาศตัวแปรกับการกําหนดคาใหตัวแปรจะเปนคนละเร่ืองกัน แตจาวายอมใหคุณรวมคําสั่งทั้งสองน้ีไวเปนคําส่ังเดียวกันไดดวย รูปของคําสั่งจะเปนดังตัวอยาง

int anInt = 5;long aLong = 10;

C:\java> javac TestVariable.javaC:\java> java TestVariable2097a

Page 33: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 4 คาคงตัวและตัวแปรพ้ืนฐาน

33

คําสั่งเริ่มดวยชื่อชนิดของตัวแปร ตามดวยชื่อของตัวแปร ตามดวยเครื่องหมายเทากับ และคาคงตัวที่ตองการกําหนดให รูปแบบคําสั่งแบบนี้ใชไดกับตัวแปรทุกชนิด ตอไปนี้เราจะใชคําสั่งแบบยอแบบนี้เปนหลัก เพ่ือความกระทัดรัด นอกจากนี้ยังเรายังประกาศหรือกําหนดคาตัวแปรมากกวาหนึ่งตัวในคําส่ังเดียวดวย หากตัวแปรเปนตัวแปรชนิดเดียวกันและคาคงตัวที่กําหนดใหเหมือนกัน เชน

int i, j;i = j = 10;

คาของตัวแปรสามารถเปล่ียนไปไดเร่ือย ๆ ดวยการกําหนดคาใหมให เราสามารถบังคับใหตัวแปรที่เราสรางขึ้นถูกกําหนดคาไดแคคร้ังเดียวไดดวยคําส่ัง final เชน

final int x = 5;

กรณีน้ี x จะมีคาเทากับ 5 ตลอดโปรแกรม จะกําหนดคาใหมใหอีกภายหลังไมไดแลว

การกําหนดคาใหกับตัวแปรทศนิยม ทําไดดังตัวอยาง

double aDouble = 10.0D;float aFloat = 1.5F;double x = 1.234e20;double y = 150;float z = 30000L

ตัวแปรทศนิยมแบบ float รับคาคงตัวทศนิยมปกติ สวนตัวแปรทศนิยมแบบ double รับคาคงตัวทศนิยมแบบปกติหรือแบบยาวก็ได นอกจากนี้ตัวแปรทศนิยมยังรับคาคงตัวจํานวนเต็มไดดวย เชน ตัวแปร y ในตัวอยางจะมีคาเปน 150.0D จาวาแปลงคาคงตัวจํานวนเต็มเปนคาคงตัวทศนิยมใหเราโดยอัตโนมัติ

ในทางตรงกันขามตวแปรจํานวนเต็มรับคาทศนิยมไมได เชน int i = 50.0D; //Error

เพราะจาวาไมตองการถือวิสาสะปดเศษทศนิยมใหถามี เพราะอาจทําใหการคํานวนของเราผิดพลาด

สําหรับตัวแปรตรรก เรากําหนดคาอยางงาย ๆ ไดดวยคาคงตัวตรรกคือคําวา true หรือ false ตัวอยางเชน

boolean x = true;boolean y = false;

Page 34: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 4 คาคงตัวและตัวแปรพ้ืนฐาน

34

การแคสเวลาคอมไพลเลอรทํางาน มันจะตรวจสอบความเขากันไดระหวางตัวแปรทางดานซาย กับคาคงตัวหรือตัวแปรทางดานขวาของเครื่องหมายเทากับ ถาเขากันไมไดมันจะไมยอมคอมไพลโปรแกรมให เราสามารถบังคับใหคอมไพลเลอรคอมไพลไดดวย การแคส ตัวอยางเชน

byte x = (byte) 130;

ปกติแลว x รับคา 130 ไมได เพราะคาสูงสุดท่ีเปนไปไดของตัวแปรแบบ byte คือ 127 เราสามารถบังคับใหคําสั่งน้ีผานไดดวยการแคส ซ่ึงก็คือการใชคําส่ัง (byte) กํากับเลข 130 คอมไพเลอรจะไมสนใจคาของตัวเลข 130 เพราะเรากํากับวาตัวเลขตัวนี้ไมวามีคาเปนเทาไหรถือวาเขากันไดกับตัวแปรแบบ byte ดังน้ันคอมไพเลอรจะปลอยผาน คําสั่งนี้จึงเปนคําสั่งที่ไมผิดหลักภาษาจาวา

แตอยางไรก็ตามผลที่ไดคือ x จะมีคาแค 127 เทาน้ัน เพราะ 127 เปนคาท่ีใกลเคียง 130 ที่สุดที่สามารถกําหนดใหตัวแปรแบบ byte ได

หรืออยางในกรณีของตัวแปร float กับคาคงตัวทศนิยมแบบยาว ถาตองการใหจับใหเทากันไดก็ใหแคสคาคงตัวทศนิยมแบบยาวใหเปน float เชน

float f = (float) 10.3D;

ในกรณีน้ีคาของ f จะเทากับ 10.3F ไมตองมีการปดเพราะในความเปนจริง float รับคาทศนิยม 10.3 ไดอยูแลว

บอยครั้งที่ทางขวาของเครื่องหมายเทากับเปนตัวแปรไมใชคาคงตัว คอมไพเลอรจะเช็คขนาดของตัวแปรแทนที่จะดูจากคาในตัวแปร และมักทําใหเกิดปญหาในการกําหนดคาขึ้น เชน

int i = 20;byte b = i; \\Error

ที่จริงแลวไมนามีปญหาเพราะตัวแปร byte รับคา 20 ไดอยูแลว แตเพราะเราใชตัวแปร i แทนที่จะใชตัวเลข 20 โดยตรง แบบนี้คอมไพลเลอรจะไมใหผาน เพราะมันจะคิดวาเปนตัวแปร i มีคามากกวา 127 ก็ได เราแกปญหาน้ีไดดวยการแคส ดังน้ี

int i = 20;byte b = (byte) i;

ตัวอยางอื่น ๆของการแคสเปนดังน้ี float f = (float) 100.5D;int i = (int) f;byte b = (byte) i;char c = (char) 3.14F;short s = (short) ‘a’;byte b = 32;char d = (char) b;

Page 35: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 4 คาคงตัวและตัวแปรพ้ืนฐาน

35

จากตัวอยางขางตนจะเห็นวาเราใชการแคสในการบังคับใหตัวแปรทางซายรับคาตัวแปรทางขวาซึ่งมีขนาดใหญกวา หรือใชการแคสในกรณีที่มีการใชตัวแปร char ในฐานะของตัวเลข จาวาจะหาคาที่เหมาะสมที่สุดที่เปนไปไดให เชน ในกรณีน้ี ตัวแปร i จะมีคา 100 สวนตัวแปร c จะมีคา \u0003 เปนตน

เคล็ดลับ วีธีที่ดีสุดในการปองกันปญหาเรื่องความเขากันไมไดของตัวแปรและคาคงตัว คือ การใชตัวแปร int หรือ longเทาน้ันสําหรับการเก็บจํานวนเต็ม และการใชตัวแปร double เทาน้ันสําหรับการเก็บทศนิยม การใชตัวแปร byte short และ float อาจดีในแงของการประหยัดเนื้อที่ในแรมแตประโยชนที่ไดไมคุมเมือ่เปรียบเทียบกับความเสี่ยงที่เกิดจากความผิดพลาดของโปรแกรมเนื่องจากความเขากันไมไดของตัวแปรและคาคงตัว

Page 36: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

5 เคร่ืองหมาย

เครื่องหมายคือสิ่งที่บอกใหจาวาเวอรชัวนแมทชีนนําคาคงตัวที่อยูในตัวแปรไปคํานวนในลักษณะที่เราตองการ เคร่ืองหมายในภาษาจาวามีอยูอยางมากมาย เคร่ืองหมายพ้ืนฐานท่ีสุดไดแก เครื่องหมายคณิตศาสตร บวก ลบ คูณ หาร

เคร่ืองหมายคณิตศาสตรเครื่องหมายคณิตศาสตรสามารถใชไดกับ คาคงตัวจํานวนเต็ม คาคงตัวทศนิยม ตัวแปรจํานวนเต็ม และตัวแปรทศนิยม มีดังน้ี

ตารางที่ตารางที่ตารางที่ตารางที่ 5555----1111 เครื่องหมายคณิตศาสตรเครื่องหมายคณิตศาสตรเครื่องหมายคณิตศาสตรเครื่องหมายคณิตศาสตร

ชื่อเคร่ืองหมาย

สัญลักษณ ชนิด ตัวอยาง

เลขบวก + เดี่ยว +5, +5.0 , +a เลขลบ - เดี่ยว -2, - 2.0, -a การบวก + คู 1 + 2, 1.0+ 2.0, a + b การลบ - คู 2 – 1, 2.0 - 1.0, a - b การคณู * คู 4 * 5, 4.0 * 5.0, a * b การหาร / คู 10 / 2, 10.0/2.0, a / b มอดูโล % คู 10 % 3, 10.0 % 3.0, a % b

เคร่ืองหมายคณิตศาสตรแบงออกเปนสองจําพวกคือ เครื่องหมายเดี่ยว กับเครื่องหมายคู

Page 37: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 5 เคร่ืองหมาย

37

เครื่องหมายเดี่ยวมีสองตัวไดแก + และ – ซึ่งเขียนอยูหนาคาคงตัวหรือตัวแปร สวนเคร่ืองหมายคูเปนการกระทํากันระหวางเลขสองตัว

เครื่องหมายหารหรือ / จะใหผลลัพธเปนจํานวนเต็ม ถาตัวตั้งเปนจํานวนเต็มทั้งคู โดยจะปดเศษทิ้งเสมอ แตถาตัวตั้งเปนเลขทศนิยมจะคงเศษไวในรูปของทศนิยม และถาตัวตั้งเปนจํานวนเต็มกับทศนิยม ผลลัพธจะเปนเลขทศนิยม

int i = 5 / 2;double d = 5.0 / 2.0;double e = 5 / 2.0;

กรณีน้ี i มีคาเทากับ 2 สวน d และ e มีคาเทากับ 2.5

เครื่องหมายโมดูโล คือการหาเศษของผลหาร ถาตัวตั้งเปนจํานวนเต็ม ผลลัพธก็คือเศษของผลหาร ถาตัวต้ังเปนเลขทศนิยม ผลลัพธก็คือเศษของผลหารเหมือนกันแตเก็บไวในรูปของเลขทศนิยม

int i = 5 % 2;double d = 5.0 % 2.0;double e = 5 % 2.0;

กรณีน้ี i มีคาเทากับ 1 สวน d และ e มีคา 1.0

ปกติแลว *, /, % จะมีลําดับความสําคัญสูงกวา +,- ดังน้ัน ถามีเครื่องหมายมากกวาหนึ่งเครื่องหมาย จาวาเวอรชัวนแมทชีนจะทํา *, /, % ใหเสร็จกอน โดยคํานวนเรียงตามลําดับจากซายไปขวา แลวจึงคอยทํา +,- โดยเรียงจากซายไปขวาเชนกัน และเราสามารถใชเครื่องหมายวงเล็บในการกําหนดใหจาวาเวอรชัวนแมทชีนเรียงลําดับความสําคัญใหมตามที่เราตองการได

int i = 3 + 5 * 4 – 4 / 2;int j = 3 + ( 5 * 4 ) – ( 4 / 2 );int k = ( 3 + 5 ) * (4 – (4 /2) );

กรณีน้ี i และ j จะมีคาเทากันคือ 21 สวน k จะมีคา 16

สวนในกรณีของเครื่องหมายบวกลบหนาตัวเลข จะมีลําดับความสําคัญสูงกวา *,/,%,+,- เสมอ

int i = -3 * -5 + +2 / +1;

กรณีน้ี i มีคาเปน 17

นอกจากนี้เครื่องหมายบวกลบหนาตัวเลขยังกระทําจากขวาไปซาย ไมใชซายไปขวา ถามีมากกวาหนึ่งตัว

int i = --4;

ในกรณีน้ี i = -(-4)) หรือ 4 น้ันเอง

Page 38: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 5 เคร่ืองหมาย

38

ผลลัพธของการกระทําคณิตศาสตรจะเปนชนิดเดียวกับตัวตั้งเสมอ เชน คาคงตัวจํานวนเต็มปกติสองตัวบวกกัน ผลลัพธที่ไดจะเปนคาคงตัวจํานวนเต็มปกติดวย หรือ ตัวแปร int บวกตัวแปร int ผลลัพธก็จะเปนคาคงตัวจํานวนเต็มปกติ แตถาเปนการกระทําระหวางตัวตั้งตางชนิดกัน ผลลัพธจะเปนชนิดเดียวกับตัวตั้งตัวที่ใหญกวาเสมอ โดยเรียงลําดับจากใหญไปเล็กดังน้ี ทศนิยมแบบยาว ทศนิยมปกติ จํานวนเต็มแบบยาว จํานวนเต็มปกติ ตัวอยางเชน ตัวแปรแบบ long บวกคาคงตัวทศนิยมปกติ จะไดผลลัพธเปนคาคงตัวทศนิยมปกติ เปนตน

ในกรณีของตัวแปร short และ byte ไมวาจะกระทํากับอะไรจะตองไดผลลัพธอยางนอยเปนจํานวนเต็มแบบปกติเสมอ เชน

byte b = 2;short s = 3int i = s * b;

ตัวแปร i ตองประกาศใหเปน int ถาประกาศใหเปน short จะรับผลลัพธของ s * b ไมได หรืออยางเชน short s = 3;s = (short) -s;

กรณีน้ีตองมีการแคส –s ใหเปน short ดวย เพราะ s ถูกกระทําดวย – แลวจะกลายเปนจํานวนเต็มแบบปกติซึ่งใหญกวาตัวแปร short

หรืออยางเชน

short h = 40;h = h + 2; // Error

ในกรณีน้ี h + 2 กลายเปนคาคงตัวขนาด 4 ไบตตามตัวตั้ง 2 พอเวลาแทนคากลับเขาไปท่ี h จะเกิดปญหา เพราะขนาดของทางขวาใหญกวาทางซาย และทางขวามีตัวแปรเปนสวนประกอบ ดังน้ันตองมีการแคสดวย

short h = 40;h = (short) (h + 2);

สังเกตวาการแกปญหาดวยวิธีการขางลางนี้ไมไดผล

short h = 40;h = h + (short) 2; //Error

เพราะแมจะปรับ 2 ใหมีขนาด 2 ไบตเทากับ h แตเมื่อถูกกระทําดวยเครื่องหมายผลลัพธจะมีขนาดอยางนอย 4 ไบตเสมอ ซึ่งใหญกวาตัวแปรทางซายของเครื่องหมายเทากับอยูดีตัวแปร char แมไมใชตัวเลข แตสามารถใชเครื่องหมายคณิตศาสตรไดดวย คาของมันจะเทากับตัวเลขของรหัสยูนิโคดที่มันแทน ลองดูตัวอยางตอไปน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 5555 ---- 1 1 1 1 : TestOperator.java: TestOperator.java: TestOperator.java: TestOperator.java

public class TestOperator {

Page 39: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 5 เคร่ืองหมาย

39

public static void main(String[]args){char x = ‘a’ ;char y = ‘b’ ;System.out.println(x+y);

}}

ในโปรแกรมน้ี เราประกาศตัวแปร char สองตัวชื่อ x และ y และกําหนดใหมีคาเปน ‘a’ และ ‘b’ ตามลําดับ เมือ่แสดงคาของ x + y จะไดผลเปนตัวเลขจํานวนเต็ม 195 ดังน้ี

ท่ีเปนเชนน้ีเปนเพราะ รหัสยูนิโคดของ ‘a’ คือ \u0061 หรือ 97 ในระบบเลขฐานสิบ สวนรหัสยูนิโคดของ ‘b’คือ \u0062 หรือ 98 เมื่อนํามาบวกกัน จาวาจะเปลี่ยนตัวอักษรทั้งสองเปนจํานวนเต็ม ทําใหไดผลลัพธเปน 195

ดังนั้นตัวแปร char สามารถกระทํากับตัวแปรจํานวนเต็มอื่นไดราวกับวาตัวมันเปนจํานวนเต็ม และผลลัพธท่ีไดทางคณิตศาสตรของตัวแปร char จะกลายเปนจํานวนเต็ม เชน

char c = ‘c’;int i = c + 4;

คาคงตัวแบบขอความสามารถใชเครื่องหมายบวกไดดวย แตผลลัพธคือการเชื่อมขอความเขาดวยกัน ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 5555 ---- 2 2 2 2 : TestOperator.j: TestOperator.j: TestOperator.j: TestOperator.javaavaavaava

public class TestOperator {public static void main(String[]args){

System.out.println(“Hello”+”World”);}

}

ผลการรันโปรแกรมขางตนเปนดังน้ี

C:\java> java TestOperator195

Page 40: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 5 เคร่ืองหมาย

40

เคร่ืองหมายอินครีเมนท

เครื่องหมายอินครีเมนทเปนเครื่องหมายทางคณิตศาสตรประเภทหนึ่ง มีความหมายดังตาราง

ตารางที่ตารางที่ตารางที่ตารางที่ 5555----2222 เครื่องหมายอินครีเมนทเครื่องหมายอินครีเมนทเครื่องหมายอินครีเมนทเครื่องหมายอินครีเมนท

สัญลักษณ ความหมาย ตัวอยาง ++ + 1 ++i , i++ - - - 1 - -i, i- -

ตัวอยางเชน

int i = 10;i++;

ทายที่สุด i จะมีคาเปน 11 หรืออีกนัยหน่ึง คําส่ัง i++ มีความหมายเหมือนกันคําสั่ง i = i + 1

ทั้ง ++i และ i++ เปนการบวกหนึ่งใหกับตัวแปร i แตมีความหมายตางกันถานําไปใชในการกําหนดคาของตัวแปร เชน

int i = 10;int j = ++i;int x = 10;int y = x++;

ตัวแปร i และ j ทายที่สุดแลวจะมีคาเปน 11 เพราะ i ซึ่งมีคา 10 ถูกบวกดวยหนึ่งกลายเปน 11 แลวนําคาใหมนี้ไปกําหนดใหกับ j ดวย สวนในกรณีของ x กับ y จะตางกัน x ทายที่สุดแลวมีคา 11 แต y จะมีคาแค 10เพราะคําส่ัง x++ จะทําการกําหนดคา y ใหมีคาเทากับ x กอน แลวจึงเพิ่มคาของ x ดวยหนึ่งทีหลัง

นอกจากการบวกและการลบดวยหน่ึงแลว จาวายังมีโอเปอรเรเตอรพิเศษอีกกลุมหน่ึงท่ีมีลักษณะคลายเคร่ืองหมายอินครีเมนท แตใชสําหรับการกําหนดตัวแปรโดยเฉพาะ

C:\java> java TestOperatorHelloWorld

Page 41: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 5 เคร่ืองหมาย

41

ตารางที่ตารางที่ตารางที่ตารางที่ 5 5 5 5----3333 เครื่องหมายอินครีเมนทเครื่องหมายอินครีเมนทเครื่องหมายอินครีเมนทเครื่องหมายอินครีเมนท

รูปแบบคําส่ัง ความหมาย x *= a x = x * a x /= a x = x / a

x %= a x = x % a x += a x = x + a x -= a x = x - a

โดยที่จะมีการแคสใหโดยอัติโนมัติดวยถาจําเปน ตัวอยางเชน

byte b = 2;b += 10;

บรรทัดท่ี (2) จะมีความหมายเหมือน b = (byte) ( (int) b + 10) ซ่ึงไดผลลัพธเปน 12 ซึ่งแตกตางกับในกรณีท่ีเราเขียนคําส่ังแบบตรง ๆ

byte b = 2;b = b + 2; //Error

แบบนี้คอมไพลไมผานเพราะตองมีการแคสดวย ดงน้ี

byte b = 2;b = (byte) (b + 2);

เคร่ืองหมายสมการและอสมการ

ตารางที่ตารางที่ตารางที่ตารางที่ 5 5 5 5----3333 เครื่องหมายสมการและอสมการเครื่องหมายสมการและอสมการเครื่องหมายสมการและอสมการเครื่องหมายสมการและอสมการ

รูปแบบคําส่ัง ความหมาย a < b a นอยกวา b หรือไม

a <= b นอยกวาหรือเทากับ หรือไม a > b มากกวา หรือไม

a >= b มากกวาหรือเทากับ หรือไม a == b เทากับ หรือไม a != b ไมเทากับ หรือไม

ตัวตั้งของเครื่องหมายแบบสมการและอสมการเปนไดทั้งตัวเลขและตัวอักษร แตผลลัพธที่ไดจะเปนคาทางตรรกซึ่งมีคาเปน true หรือ false เทานั้นและมีคาเทียบเทากับตัวแปรตรรก แมวาตัวตั้งจะไมใชตัวแปรตรรกก็ตาม

int b = 5;boolean y = b > 4;

ในกรณีน้ี y มีคาเทากับ true

Page 42: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 5 เคร่ืองหมาย

42

เคร่ืองหมายแบบสมการและอสมการ ไมตองมีการแคส แมวา b และ 4 จะไมใชตัวแปรแบบตรรก วลี b > 4 เปนวลีทางตรรกศาสตร ซึ่งมึคาเปนจริงหรือเท็จ ซึ่งเขากันไดกับตัวแปร y ซึ่งเปนตัวแปรแบบ boolean อยูแลว

สังเกตวาเครื่องหมายเทากับใชเครื่องหมายเทากับสองอัน เพราะเคร่ืองหมายเทากับอันเดียวเปนสัญลักษณของการกําหนดคาตัวแปร ไมใชเคร่ืองหมายสมการและอสมการ

เคร่ืองหมายตรรกเครื่องหมายตรรกใชเชื่อม คาคงที่ตรรก ตัวแปรตรรก และวลีที่เกิดจากเครื่องหมายแบบสมการและอสมการ ผลลัพธท่ีจะเปนคาความจริงทางตรรก

ตารางที่ตารางที่ตารางที่ตารางที่ 5 5 5 5----4444 เครื่องหมายตรรกเครื่องหมายตรรกเครื่องหมายตรรกเครื่องหมายตรรก

รูปแบบคําส่ัง ความหมาย !x คาความจริงทีต่รงขามกับ x

x & y คาความจริงของ x AND y x | y คาความจริงของ x OR y x ^ y คาความจริงของ x XOR y

x && y คาความจริงของ x AND y x || y คาความจริงของ x OR y

คาความจริงทางตรรกศาสตรเปนดังตาราง

ตารางที่ตารางที่ตารางที่ตารางที่ 5 5 5 5----5 5 5 5 ตารางคาความจริงตารางคาความจริงตารางคาความจริงตารางคาความจริง

x y !x x & y x | y x ^ y x && y x || y true true false true true false true true true false false false true true false true false true true false true true false true false false true true false false false false

ตัวอยาง

boolean b = true;boolean c = b & ( 4 > 5 );boolean d = !c;

ตัวแปร c ในตัวอยางขางตนมีคาเทากับ false สวนตัวแปร d มีคา true

สังเกตวาเครื่องหมาย & และ && มีคาความจริงเหมือนกันทุกประการ เครื่องหมาย | กับ || ก็เชนเดียวกัน ที่จริงแลวมีความแตกตางกันเล็กนอย กลาวคือเคร่ืองหมาย & และ | จะหาผลลัพธทางตรรกขางซายและขางขวาของมันจนเสร็จเสมอ ในขณะที่ && และ || มีลักษณะ ลัดวงจร กลาวคือ ถาผลลัพธสามารถหาไดโดยไมตองคํานวนจนจบมันจะหยุดคํานวนทันที ดังตัวอยาง

Page 43: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 5 เคร่ืองหมาย

43

int i = 10;boolean b = false & (i++ > 11) ;

ตัวอยางนี้ในที่สุดจะได b มึคา false และ i มึคาเปน 11 ในขณะที่

int i = 10boolean b = false && (i++ > 11);

จะได b มีคา false เชนกัน แต i จะมีคาแค 10 เพราะสําหรับเคร่ืองหมาย && ถาขางใดขางหนึ่งของเครื่องหมายเปน false เรารูทันทีวาผลลัพธตองเปน false แนนอน ในกรณีน้ีดานซายของเคร่ืองหมายเปน falseดังนั้นจาวาเวอรชัวนแมทชีนจะทิ้งสิ่งที่อยูทางขวาของเครื่องหมายไปเลย ทําใหไมมีการบวกหนึ่งใหกับ i เกินข้ึน

ลองดูวลีทางตรรกท่ีซับซอนข้ึน

int d = 10;char m = ‘x’;boolean r = (d > 4) && (5.5 < 3.0) || (m == ‘x’);

ตวอยางนี้ตัวแปร r จะมีคาเปนจริง เพราะวลี d > 4 มีคาเปนจริง วลี 5.5 < 3.0 เปนเท็จ สวนวลี m ==

‘x’ มีคาเปนจริง เม่ือนําสามวลีมากระทํากันจะไดเปน จริง && เท็จ || จริง ซึ่งจาวาเวอรชัวนแมทชีนจะเริ่มกระทําจากซายไปขวา หรือเทากับ ((จริง && เท็จ) || จริง) ซ่ึงก็คือ ( เท็จ || จริง ) ซ่ึงก็คือ จริง ในที่สุด

ลําดับความสําคัญของเครื่องหมายแบบสมการและอสมการที่มากกวาเครื่องหมายตรรก ดังน้ันถาไมใสวงเล็บ จาวาเวอรชัวนแมทชีนจะทําเครื่องหมายแบบสมการและอสมการจนเสร็จหมดกอน แลวจึงคอยทําเครื่องหมายตรรก

เครื่องหมายตอไปนี้เปนเครื่องหมายตรรกแบบที่ใชสําหรับการกําหนดคาใหตัวแปร boolean โดยเฉพาะ

ตารางที่ตารางที่ตารางที่ตารางที่ 5555----6666 เครื่องหมายเครื่องหมายเครื่องหมายเครื่องหมายตรรกตรรกตรรกตรรก

รูปแบบคําส่ัง ความหมาย b &= a b = b & a b ^= a b = b ^ a b |= a b = b | a

ตัวอยางเชน

boolean b = true;b &= 5.5 <= 3.0

ในกรณีน้ี b จะไดคาเปนเท็จ เพราะ b = (b & ( 5.5 <= 3.0))

เคร่ืองหมายบิตเครื่องหมายบิตเปนเครื่องหมายที่ใชกับการคํานวนดิจิตอล มีดังน้ี

Page 44: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 5 เคร่ืองหมาย

44

ตารางที่ตารางที่ตารางที่ตารางที่ 5 5 5 5----7 7 7 7 เครื่องหมายบิตเครื่องหมายบิตเครื่องหมายบิตเครื่องหมายบิต

ชื่อเคร่ืองหมาย รูปแบบคําส่ัง ความหมาย Bitwise NOT ~a (ดูไดในตารางคาความจริง) Bitwise AND a & b (ดูไดในตารางคาความจริง) Bitwise OR a | b (ดูไดในตารางคาความจริง)

Bitwise XOR a ^ b (ดูไดในตารางคาความจริง) Shift left a << n เลื่อนทุกบิตใน a ไปทางซาย n

ตําแหนง เติมศูนยเขาทางขวา Shift right with

sign bit a >> n เลื่อนทุกบิตใน a ไปทางขวา n

ตําแหนง เติมทางซายดวยบิตเครื่องหมายของ a

Shift right with zero fill

a >>> n เลื่อนทุกบิตใน a ไปทางขวา n ตําแหนง เติมทางซายดวย 0

ทางซายและทางขวาของเครื่องหมายตองเปน จํานวนเต็ม โดยถาเปนคาคงตัวแบบ 4 ไบต, ตัวแปรแบบ int,short หรือ byte ใหมองเปนเลขฐานสอง 32 บิต สวนคาคงตัวแบบ 8 ไบตหรือตัวแปรแบบ long ให มองเปนเลขฐานสอง 64 บิต

สังเกตวามีการใชเครื่องหมาย & และ | ซ้ํากับเครื่องหมายตรรก แตในกรณีของเครื่องหมายตรรก ทางซายและทางขวาของเคร่ืองหมายจะเปนสมการตรรกศาสตร สวนในกรณีของเครื่องหมายบิตจะเปนจํานวนเต็ม

ตารางผลลัพธของเครื่องหมายบิตเปนดังนี้ตารางที่ตารางที่ตารางที่ตารางที่ 5 5 5 5----8 8 8 8 ตารางผลลัพธของเครื่องหมายบิตตารางผลลัพธของเครื่องหมายบิตตารางผลลัพธของเครื่องหมายบิตตารางผลลัพธของเครื่องหมายบิต

x y ~x x & y x | y x ^ y 1 1 0 1 1 0 1 0 0 0 1 1 0 1 1 0 1 1 0 0 1 1 0 0

เครื่องหมายตอไปนี้เปนเครื่องหมายบิตที่มีไวสําหรับการกําหนดคาใหตัวแปรโดยเฉพาะตารางที่ตารางที่ตารางที่ตารางที่ 5 5 5 5----9999 เครื่องหมายบิตเครื่องหมายบิตเครื่องหมายบิตเครื่องหมายบิต

รูปแบบคําส่ัง ความหมาย b &= a b = b & a b |= a b = b | a b ^= a b = b ^ a

x <<= a x = x << a x >>= a x = x >> a

x >>>= a x = x >>> a

สําหรับเครื่องหมายแบบบิตนี้ไมขอลงรายละเอียด เนื่องจากมีที่ใชนอย

Page 45: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

6 บลอคเง่ือนไข

บลอคเงื่อนไขคือการสั่งใหจาวาเวอรชัวนแมทชีนตัดสินใจภายใตเงือ่นไขท่ีเรากําหนดข้ึน มีอยูดวยกันสองคําส่ังคือ if และ switch

คําส่ัง ifลองดูตัวอยางคําส่ัง if ที่งายที่สุดในโปรแกรมตัวอยางขางลางนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 6 6 6 6 ---- 1 1 1 1 : TestIf.java: TestIf.java: TestIf.java: TestIf.java

public class TestIf{public static void main(String[]args){

int i = 1;int j = 3;

if (j > 0) i = 4;System.out.println(“i = “ + i);

}}

ในโปรแกรมนี้ตอนแรกเรากําหนดคาใหตัวแปร i เทากับ 1 และ j เทากับ 3 ตอมาเราใชคําสั่ง if ในการพิจารณาเงื่อนไขวา ถา j มีคามากกวา 0 ใหเปลี่ยนคาของ i เปน 4

Page 46: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 6 บล็อคเงื่อนไข

46

เน่ืองจาก j มีคาเปน 3 อยูกอนแลว และ 3 มากกวา 0 ดังน้ันเง่ือนไขน้ีเปนจริง คําส่ัง if จึงทํางาน เปนผลให iเปล่ียนคาเปน 4 เมื่อพิมพผลลัพธออกหนาจอจะไดคาของ i เปน 4

น้ันคือคําส่ัง if จะตามดวยวงเล็บ ส่ิงท่ีอยูในวงเล็บคือเง่ือนไข ซึ่งอาจอยูในรูปของเงื่อนไขทางตรรกซึ่งตองมีคาเปนจริงหรือเท็จเทานั้น ถาจริงจาวาเวอรชัวนแมทชีนจะทําคําสั่งที่ตามหลังวงเล็บมา แตถาเปนเท็จคําสั่งที่ตามหลังวงเล็บมาก็จะถูกขามไปเลย เชนในกรณีของตัวอยางขางตน ถาเปนเท็จ i ก็จะยังคงเทากับ 1 เมื่อพิมพออกหนาจอ

ลองพิจารณาคําส่ัง if อีกรูปแบบหนึ่งในโปรแกรมขางลาง

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 6 6 6 6 ---- 2 2 2 2 : TestIf.ja: TestIf.ja: TestIf.ja: TestIf.javavavava

public class TestIf{public static void main(String[]args){

int i;int j = 1;if (j > 2)

i = 4;else

i = 1;System.out.println(“i = “ + i);

}}

คําส่ัง if ในโปรแกรมนี้ยาวขึ้นอีกนิดหนึ่ง คือมี else ตอทาย จาวาเวอรชัวนแมทชีนจะพิจารณาเงื่อนไขในวงเล็บของคําส่ัง if ถาจริงจะทําคําสั่งที่อยูตอทายวงเล็บ ถาเปนเท็จแทนที่จะกระโดดขามไปเลยจะทําคําสั่งที่อยูทายคําวา else แทนกอนจะจากไปทําคําสั่งที่อยูถัดไป

ในโปรแกรมนี้ตอนแรกเราไมไดกําหนดคาใด ๆให i เมื่อโปรแกรมทํางานมาถึงคําสั่ง if และพบวาเงื่อนไขที่อยูในวงเล็บเปนเท็จ มันจะขามคําสั่ง i = 4 ไป แลวทําคําส่ัง i = 1 แทน จากนั้นคอยพิมพออกหนาจอซึ่งยอมได i= 1

โปรดสังเกตวาตองมี ; อยูหนา else ดวยทั้งๆ ที่ทั้งหมดเปนคําสั่งเดียวกัน

บางครั้งเราตองการใหทําคําสั่งมากกวาหนึ่งคําสั่ง เราสามารถใชวงเล็บปกกาในการครอบกลุมของคําส่ังไดดวย เราเรียกกลุมของคําสั่งที่ถูกครอบดวยเครื่องหมายปกกาวา บลอคปกกา ดังตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 6666 ---- 3 3 3 3 : TestIf.java: TestIf.java: TestIf.java: TestIf.java

public class TestIf{

Page 47: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 6 บล็อคเงื่อนไข

47

public static void main(String[]args){int i, k, l ;int j = 1;if (j > 2) {

i = 4;k = 5;l = 2;

} else {i = 1;k = 1;l = 4;

}System.out.println(“i = “ + i);System.out.println(“k = “ + k);System.out.println(“l = “ + l);

}}

ในกรณีน้ีถาเง่ือนไขในวงเล็บเปนจริง จาวาเวอรชัวนแมทชีนจะคําสั่งทั้งหมดที่อยูในบลอคปกกาที่อยูตามหลังวงเล็บเง่ือนไข แตถาเปนเท็จจะทําคําสั่งทั้งหมดที่อยูในบลอคปกกาที่อยูหลัง else

กรณีท่ีเราบลอคปกกาเราไมจําเปนตองมี ; หนา else อีกตอไป อีกท้ังเม่ือจบบลอคปกกา เราสามารถละเคร่ืองหมาย ; ไดดวย

ตอไปน้ีเปนตัวอยางของการใชบลอคปกกาผสมกับการใชคําส่ังเด่ียว ๆ

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 6 6 6 6 ---- 4 4 4 4 : TestIf.java: TestIf.java: TestIf.java: TestIf.java

public class TestIf{public static void main(String[]args){

int i, k, l ;int j = 1;if (j > 2)

i = 4;else {

i = 1;k = 1;l = 4;

}System.out.println(“i = “ + i);

}}

Page 48: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 6 บล็อคเงื่อนไข

48

แบบนี้คุณยังคงตองมีเครื่องหมาย ; หนา else เพราะ คําส่ังหลังวงเล็บเง่ือนไขเปนคําส่ังเด่ียว ลงพิจารณาอีกตัวอยางหน่ึงซ่ึงกลับกัน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 6666 ---- 5 5 5 5 : TestIf.java: TestIf.java: TestIf.java: TestIf.java

public class TestIf{public static void main(String[]args){

int i, k, l ;int j = 1;

if (j > 2) {i = 4;k = 5;l = 2;

} elsei = 1;

System.out.println(“i = “ + i);}

}

กรณีน้ีคําส่ังหลังวงเล็บเง่ือนไขเปนบลอคปกกา สวนคําส่ังหลัง else เปนคําส่ังเด่ียว ดังนั้นตองมีเครื่องหมาย ;ตามหลังคําสั่งเดี่ยวดวย

คําส่ัง if ทั้งที่มี else และไมม ีelse สามารถซอนกันเปนหลาย ๆชั้นไดดังตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 6666 ---- 6666 : TestIf.java: TestIf.java: TestIf.java: TestIf.java

public class TestIf{public static void main(String[]args){

int i, j, k;i = j = k = 1;if (j > 0)

if (k == 1) i = 1;else

if (k == 2)i = 4;

elsei = 5;

System.out.println(“i = “ + i);}

}

Page 49: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 6 บล็อคเงื่อนไข

49

การทํางานของโปรแกรมน้ีจะเร่ิมจากการประการและกําหนดคาของตัวแปร i, j และ k ใหเทากับ 1 จากนั้นพิจารณาเง่ือนไขในวงเล็บคือ j>0 หรือไม ถาใช จะทดสอบเงื่อนไขวา k == 1 หรือไม ถาใชคําสั่ง i = 1 ก็จะทํางาน แตถาไมใชจะขามไปยัง else ตัวแรก ซ่ึงเร่ิมจากการตรวจสอบเง่ือนไข k == 2 ถาจริงก็จะทําคําสั่ง i =

4 แตถาไมก็จะทําคําสั่ง i = 5 แทน กอนท่ีจะทําคําส่ังถัดไปคือ การพิมพคาของ i ออกหนาจอ

ลองดูตัวอยางอีกตัวอยางหนึ่ง

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 6 6 6 6 ---- 7 7 7 7 : : : : TestIf.javaTestIf.javaTestIf.javaTestIf.java

public class TestIf{public static void main(String[]args){

int i, j, k;i = j = k = 1;if (j > 0) {

if (k == 1) i = 1;if (k == 2) i = 3;

} else {if (k == 1) i = 5;if (k != 2)if (k >= 2) i = 7;

elsei = 4;

}System.out.println(“i = “ + i);

}}

โปรแกรมนี้เปนการใชคําสั่ง if ที่มีการซอนกันหลายชั้นเหมือนกันแตมีการใชบลอคปกกาดวย คําส่ัง i = 4 ตอนทายเปน else ของคําส่ัง if (k >= 2) ไมใช else ของคําส่ัง if (k != 2) ดังนั้นตองระวังใหดีเนื่องจากการยอหนาแบบนี้ทําใหเกิดการเขาใจผิด เราควรยอหนาแบบนี้แทน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 6666 ---- 8888 : TestIf.java: TestIf.java: TestIf.java: TestIf.java

public class TestIf{public static void main(String[]args){

int i, j, k;i = j = k = 1;if (j > 0) {

if (k == 1) i = 1;if (k == 2) i = 3;

} else {if (k == 1) i = 5;

Page 50: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 6 บล็อคเงื่อนไข

50

if (k != 2)if (k >= 2)

i = 7;else

i = 4;}System.out.println(“i = “ + i);

}}

การตัดสินวา else หนึ่งๆ เปนของ if ตัวไหน มีหลักงาย ๆคือ มันจะเปนของ if ตัวที่อยูใกลที่สุดเสมอ

เคล็ดลับ วิธีการท่ีดีท่ีสุดในการปองกันความสับสนของคําส่ัง if คือ การใชบลอคปกกาเสมอแมวาจะมีคําสั่งแคคําสั่งเดียวในเง่ือนไข โปรแกรมจะอานงายขึ้นมาก

ส่ิงสําคัญอีกอยางหน่ึงเก่ียวกับการใชบลอคปกกาคือ ถามีการประกาศตัวแปรภายในบลอคปกกาตัวแปรนั้นจะถูกเรียกใชไดเฉพาะภายในบลอคปกกาเทาน้ัน เชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 6 6 6 6 ---- 9 9 9 9 : TestIf.java: TestIf.java: TestIf.java: TestIf.java

public class TestIf{public static void main(String[]args){

int j = 1;if (j == 1) {

int i = 2;}System.out.println(“i = “ + i); // (1) Error

}}

โปรแกรมนี้คอมไพลไมผานเพราะตัวแปร i ถูกประกาศไวภายใตบลอคปกกาของคําสั่ง if ไมสามารถถูกกลาวถึงนอกบลอคไดอยางในบรรทัด (1)

และเน่ืองจากตัวแปรท่ีประกาศภายในบลอคปกกาอยูแตในบลอคปกกาเทานั้นเราจึงประกาศตัวแปรใหมที่มีชื่อซ้ํากับตัวแปรในบลอคปกกาไดหลังจากบลอคปกการจบไปแลว เชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 6 6 6 6 ---- 10 10 10 10 : TestIf.java: TestIf.java: TestIf.java: TestIf.java

Page 51: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 6 บล็อคเงื่อนไข

51

public class TestIf{public static void main(String[]args){

int j = 1;//int i = 1; //(1) Errorif (j == 1) {

int i = 2; // (2)}int i = 1; // (3)

}}

ถาคําส่ังในบรรทัด (1) ไมถูกกันไวดวยเครื่องหมาย // โปรแกรมจะคอมไพลไมผานเพราะตัวแปร i ที่สรางขึ้นในบรรทัด (1) จะคงอยูตลอดทั้งโปรแกรม เมื่อประกาศตัวแปรชื่อเดิมอีกภายในบลอคปกกาในบรรทัด (2) จะเกิดความซ้ําซอนขึ้น ในทางตรงกันขามหากเราเอาคําสั่งในบรรทัด (1) ออก คําส่ังในบรรทัด (2) และมีไมมีปญหาและจะไมขัดแยงกับคําสั่งในบรรทัด (3) ดวยเพราะตัวแปร i ในบรรทัด (2) จะหายไปทันทีที่จบบลอค if จึงประกาศตัวแปร i ตัวใหมไดในบรรทัด (3)

คําส่ัง switchถาในกรณีที่เราตองการใหจาวาเวอรชัวนแมทชีนตัดสินใจวาตัวแปรตัวหนึ่งมีคาเทาไร แลวคาที่เปนไปไดมีหลายคา เราอาจใชคําสั่ง if ซอนกันไปเร่ือย ๆดังน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 6666 ---- 10 10 10 10 : T: T: T: TestIf.javaestIf.javaestIf.javaestIf.java

public class TestIf{public static void main(String[]args){

int i;int j = 3;if (j == 1)

i = 1 ;else

if (j == 2)i = 2;

elseif (j == 3)

i = 3;else

if (j == 4)i = 4;

elsei = 5;

System.out.println (“i = “ + i);}

}

Page 52: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 6 บล็อคเงื่อนไข

52

แตคําสั่งจะยาวและดูยาก เราสามารถใชคําส่ัง switch ซ่ึงออกแบบมาเพ่ือการน้ีโดยเฉพาะ

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 6666 ---- 11111 1 1 1 : TestSwitch.java: TestSwitch.java: TestSwitch.java: TestSwitch.java

public class TestSwitch{public static void main(String[]args){

int i;int j = 3;switch (j) {

case (1) : i = 1 ; break;case (2) : i = 2 ; break;case (3) : i = 3 ; break;case (4) : i = 4 ; break;default : System.out.println(“i = “ + i);

}

}}

ส่ิงท่ีอยูในวงเล็บหลังคําส่ัง switch จะเปนตัวแปร int, short, byte หรือ char ก็ได โดยจาวาเวอรชัวนแมทชีนจะทําการเทียบคาของตัวแปรนั้นกับคาที่อยูในวงเล็บหลังคําส่ัง case ถาตรงจะ ทําคําสั่งหลังเครื่องหมาย ;ถาไมตรงจะ ขามไป เปนเชนนี้เรื่อยไปจนมาถึงคําวา default จะทําคําสั่งที่อยูหลัง default เสมอไมวาที่ผานมาจะทําคําสั่ง case หรือไม ซึ่งจริง ๆแลวบลอค default ไมจําเปนตองมีก็ไดถาไมจําเปน

คําสั่งที่อยูหลังเครื่องหมาย : ของคําส่ัง case อาจมีมากกวาหนึ่งคําสั่งก็ได โดยเขียนเรียงกันไปเร่ือย ๆ โดยมีเครื่องหมาย ; ค้ันระหวางคําส่ังแตละคําส่ัง แตสุดทายตองจบดวยคําสั่ง break เสมอ

ลองพิจารณาโปรแกรมน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 6 6 6 6 ---- 12 12 12 12 : TestSwiTestSwiTestSwiTestSwitch.javatch.javatch.javatch.java

public class TestSwitch{public static void main(String[]args){

int i;int j = 3;switch (j) {

case (1) : i = 1 ;case (2) : i = 2 ;

Page 53: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 6 บล็อคเงื่อนไข

53

case (3) : i = 3 ;case (4) : i = 4 ;default : System.out.println (“i = “ + i);

}

}}

โปรแกรมนี้ตัดคําสั่ง break ออกไป ผลที่ไดก็คือจาวาเวอรชัวนแมทชีนจะพิมพเลข 4 ออกมาแทนท่ีจะเปนเลข 3 เหมือนเดิม เนื่องจากถาไมมีเครื่องหมาย break เมื่อใดที่พบวา j มีคาเทากับ case ใดก็ตาม case ท่ีเหลือท้ังหมดที่ตามมาจะทํางานดวยทันที ในกรณีน้ีเม่ือมาถึง case (3) ซึ่งตรงกับคาของ j ตัวแปร i จะถูกกําหนดคาใหเปน 3 แตจะโปรแกรมจะยังไมออกจากบลอค switch แตโปรแกรมจะทํา case อื่นที่เหลือถัดไปทั้งหมด ทําใหตัวแปร i ถูกกําหนดคาใหเปน 4 ทับคาเดิมอีกที โปรแกรมจึงพิมพวา i = 4 ในตอนสุดทาย

เคร่ืองหมาย ? :

กอนจะจบคําส่ังเง่ือนไข ขอแนะนําใหรูจักกับเครื่องหมายตัวหนึ่งในภาษาจาวาซึ่งมึลักษณะคลายคําส่ังเง่ือนไข คือ เครื่องหมาย ? : ตัวอยางการใชงานเปนดังน้ี

boolean b = false;int a = b ? 10 : 20;

เครื่องหมาย ? : มีไวใชในการกําหนดคาตัวแปรเปนหลัก ตัวแปร a ในตัวอยาง เปนตัวแปร int แตถูกจับใหมีคาเทากับ b ? 10 : 20 คาของวลี b ? 10 : 20 จะมีคาเทากับ 10 เมื่อ b เปนจริง และจะมีคาเทากับ 20 เมื่อ b เปนเท็จ ในตัวอยาง b มีคาเปนเท็จอยูกอนแลว ดังน้ัน a จึงมึคาเปน 20

เครื่องหมาย ? : สามารถซอนกันหลาย ๆ ชั้นไดดวย ตัวอยางเชน

boolean b = false;boolean c = true;boolean d = false;char x = b?c?d?’m’:’n’:’o’:’p’;

วลี b?c?d?’m’:’n’:’o’:’p’ เทียบไดกับ (b?(c?(d?’m’:’n’):’o’):’p’) น้ันคือ จาวาเวอรชัวนแมทชีนจะเริ่มพิจารณาจากวงเล็บในสุดกอน d มีคาเปนเท็จ ดังน้ันวงเล็บในสุดมีคาเทียบเทา ‘n’ ในวงเล็บชั้นถดมา c มีคาเปนจริง ดังนั้นจะมีคาเทียบเทา ‘n’ อีก สวนสุดทายในวงเล็บนอกสุด b มึคาเปนเท็จ ดังนั้นจึงมีคาเทียบเทา ‘p’ น้ันคือ x จะมีคาเทากับ ‘p’

Page 54: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

7 บลอควนลูป

สิ่งหนึ่งที่คอมพิวเตอรทําไดดีกวามนุษยคือ การทํางานเกาซํ้า ๆซาก ๆ เปนรอยเปนพันคร้ัง คอมพวิเตอรไมเคยเหน่ือย ไมเคยเบื่อ และ ไมเคยบน

บลอควนลูปคือคําสั่งที่ทําใหจาวาเวอรชัวนแมทชีนทําคําสั่งใดคําส่ังหน่ึงหรือบลอคปกกาซํ้า ๆกันหลาย ๆคร้ัง คําส่ังวนลูปในภาษาจาวาไดแกคําสั่ง while และคําส่ัง for

คําส่ัง whileลองพิจารณาโปรแกรมที่มีคําสั่ง while อยางงายอยูดังนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 7 7 7 7 ---- 1111 : TestWhile.java: TestWhile.java: TestWhile.java: TestWhile.java

public class TestWhile{public static void main(String[]args){

while (true) System.out.println(“Hello World”);}

}

Page 55: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 7 บล็อควนลูป

55

โปรแกรมนี้จะพิมพคําวา Hello World ออกหนาจอไปเร่ือย ๆเปนรอยเปนพันบรรทัด ไมมีวันหยุด คําส่ัง while ที่อยูขางหนาคําสั่งเขียนขอความออกหนาจอเปนการบอกใหโปรแกรมทําคําส่ังในบรรทัดน้ีซํ้าแลวซํ้าเลา

โปรแกรมจะทําคําสั่งในบรรทัด while ไปเร่ือย ๆตราบใดที่คาความจริงในวงเล็บที่ตามหลังคําสั่ง while มีคาเปนจริง ในกรณีน้ีส่ิงท่ีอยูในวงเล็บคือคาคงตัว true ซึ่งมีคาเปนจริงเสมอโปรแกรมจึงพิมพขอความ Hello World

ซํ้าแลวซํ้าเลาไมส้ินสุด การทํางานซํ้า ๆโดยที่เราไมตองเขียนคําสั่งเดิมหลาย ๆครั้งในโปรแกรมเดียวกันทําใหชีวิตงายขึ้น แตการทําซ้ํา ๆอยางไมมีวันหยุดคงไมคอยดีเทาไรนัก เราสามารถกําหนดใหคําส่ัง while ทําคําสั่งที่ตามมาซ้ํากี่ครั้งก็ไดตามใจเราดวยการสรางเงื่อนไขในวงเล็บที่ตามมาใหมีคาเปลี่ยนจากจริงเปนเท็จภายหลังไดดังตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 7 7 7 7 ---- 2 2 2 2 : Test: Test: Test: TestWhile.javaWhile.javaWhile.javaWhile.java

public class TestWhile{public static void main(String[]args){

int i = 1;while (i < 100) i++; //(1)System.out.println(“i = “ + i);

}}

เมื่อจาวาเวอรชัวนแมทชีนพบคําสั่ง while มันจะตรวจสอบเงื่อนไขในวงเล็บที่ตามมา ซ่ึงในกรณีน้ีก็คือ i <

1000 ถาเง่ือนไขเปนจริง มันจะทําคําสั่งที่อยูหลังวงเล็บเงื่อนไข เมื่อเสร็จแลวมันจะตรวจเงื่อนไขเดิมซ้ําอีกครั้ง ถาเงื่อนไขยังเปนจริงอยู มันจะทําคําสั่งที่อยูหลังวงเล็บเงื่อนไขอีกเชนนี้เรื่อยไปจนกวาจะพบวาเงื่อนไขมีคาเปนเท็จ จึงจะหลุดจากลูป

ในกรณีเมื่อโปรแกรมทํางานมาถึงบรรทัด (1) โปรแกรมจะบวกคาของ i ดวยหนึ่ง ไปเร่ือย ๆจนกวา i จะมีคาเทากับ 100 ซึ่งทําใหเงื่อนไขในวงเล็บที่อยูหลังคําสั่ง while เปนเท็จ จึงหลุดออกจากลูป แลวทําคําสั่งในบรรทัดตอไปซึ่งจะพิมพคา i = 100 ออกมาที่หนาจอ

คําสั่งที่ตามหลัง while มา อาจเปนบลอคปกกาก็ได เชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 7777 ---- 3 3 3 3 : TestWhile.java: TestWhile.java: TestWhile.java: TestWhile.java

C:\java> java TestWhilei=100

Page 56: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 7 บล็อควนลูป

56

public class TestWhile{public static void main(String[]args){

int i = 1;while (i < 100) {

i++;System.out.println(“i = “ + i);

}System.out.println(“Finished”);

}}

คําส่ังทุกคําส่ังในบล็อกปกกาหลังคําส่ัง while จะถูกทํางานซ้ําจนกวาเงื่อนไขในวงเล็บหลังคําสั่ง while จะเปนเท็จ ในกรณีนี้โปรแกรมจะบวกหนึ่งใหกับ i และพิมพคา i ออกมาหนาจอทุกครั้งหลังการบวก ทําอยางน้ีเร่ือยไปหนึ่งรอยครั้ง แลวปดทายดวยคําวา Finished ครั้งเดียวตอนจบโปรแกรม

คําส่ัง while ยังมีอีกรูปแบบหนึ่งที่เราเรียกวาคําสั่ง do-while ดังตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 7777 ---- 4 4 4 4 : TestWhile.java: TestWhile.java: TestWhile.java: TestWhile.java

public class TestWhile{public static void main(String[]args){

int i = 1;do {

i++;System.out.println(“i = “ + i);

} while (i < 100);System.out.println(“Finished”);

}}

โปรแกรมน้ีใหผลเหมือนโปรแกรม 7-3 เพียงแตขอแตกตางอยูตรงที่เวลาตรวจสอบเงื่อนไข จาวาเวอรชัวนแมทชีนจะทําคําสั่งที่อยูในลูปกอนแลวคอยตรวจสอบเงื่อนไขในวงเล็บที่อยูหลังคําส่ัง while ดังนั้นคําสั่งที่อยูในลูปจะตองถูกใชงานอยางนอยหนึ่งครั้งเสมอคือครั้งแรกสุดไมวาเงื่อนไขที่อยูในวงเล็บจะเปนอยางไร ในขณะที่การใชคําสั่ง whileแบบไมม ีdo คําสั่งในลูปอาจไมเคยถูกใชงานเลยถาเงื่อนไขไมเปนจริงตั้งแตแรก

ถามีการประกาศตัวแปรภายในบล็อค while เราจะอางถึงตัวแปรน้ันไดอีกเฉพาะภายในบล็อกเทาน้ันเชนเดียวกับคําส่ัง if ตัวแปรจะหมดสภาพทันทีที่โปรแกรมหลุดจากบล็อก

Page 57: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 7 บล็อควนลูป

57

คําส่ัง forคําส่ังเปนคําส่ังวนลูปอีกประเภทหน่ึงซ่ึงมีรูปแบบคําส่ังดังตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 7 7 7 7 ---- 5 5 5 5 : TestFor.java: TestFor.java: TestFor.java: TestFor.java

public class TestFor{public static void main(String[]args){

for (int i = 1; i <= 100; i++)System.out.println(“i = “ + i);

System.out.println(“Finished”);

}}

ภายในวงเล็บที่ตามหลังคําสั่ง for จะแบงเปนสามสวนและขั้นดวยเครื่องหมาย ; สวนที่หนึ่งเปนสวนที่ใชประกาศและกําหนดคาตัวแปรจํานวนเต็ม ที่เราจะใชเปนตัวนับจํานวนครั้งในการวนลูป สวนที่สองเปนเงื่อนไขที่ใหตรวจสอบ ตราบใดที่เงื่อนไขยังเปนจริงอยูใหโปรแกรมทําการวนลูปตอไปอีก และสวนที่สามคือสวนที่ใชเปลี่ยนคาของตัวแปรที่ใชนับจํานวนครั้ง ทุกครั้งที่ทําครบหนึ่งลูป ดังในตัวอยางเราประการตัวแปร i และกําหนดคาเริ่มตนใหเทากับ 1 จากนั้นโปรแกรมจะตรวจสอบเงื่อนไขในสวนที่สอง ถาเปนจริงก็จะทําคําสั่งที่อยูในลูป แลวเพิ่มคาของ i อีกหน่ึง ตรวจสอบเงื่อนไขใหม ทําไปเร่ือย ๆจนกวาเงื่อนไขจะเปนเท็จคอยออกจากลูป ซ่ึงในกรณีน้ีจะมีการวนลูปท้ังส้ิน 100 คร้ัง และตัวแปร i มีคาเริ่มจาก 1 จนถึง 100 ในการวนลูปคร้ังสุดทาย หลังจากนั้นเงื่อนไขจะเปนเท็จแลว เพราะ i จะมีคาเปน 101 ซึ่งมากกวา 100

ถาตองการวนลูปโดยใหตัวแปรนับจํานวนลูปมีคาลดลงก็ทําไดเชนกัน ตัวอยางเชน

for (int i = 100; i >= 1; i--)

ในกรณีนี้ตัวแปร i จะเริ่มตนจาก 100 และจะลดลงเร่ือย ๆทีละหนึ่งตอการวบลูปหนึ่งครั้งจนมีคาเทากับ 1 ในการวนลูปคร้ังท่ี 100 ซ่ึงเปนคร้ังสุดทาย

ตัวแปรนับจํานวนลูปในคําสั่ง for จะเกิดขึ้นเมื่อโปรแกรมเริ่มวนลูป และจะหายไปเม่ือส้ินสุดการวนลูป ดงนั้นเราไมสามารถใชตัวแปรนับจํานวนลูปนอกลูป for ได ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 7 7 7 7 ---- 6 6 6 6 : TestFor.java: TestFor.java: TestFor.java: TestFor.java

public class TestFor{public static void main(String[]args){

for (int i = 1;i >= 100; i++)System.out.println(“Hello World”);

Page 58: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 7 บล็อควนลูป

58

System.out.println(“i = “ + i); // Error

}}

โปรแกรมคอมไพลไมผานเนื่องจากเรามันไมรูจักตัวแปรชื่อ i ท่ีอยูนอกลูป for และในกรณีที่มีตัวแปรชื่อ i อยูกอนแลวในโปรแกรม เราไมอาจใชชื่อ i ไดอีกในการตั้งชื่อตัวแปรนับจํานวนลูป for เพราะตัวแปร i ท่ีอยูนอกลูปจะคงอยูตลอดทั้งโปรแกรม

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 7 7 7 7 ---- 7 7 7 7 : TestFor.java: TestFor.java: TestFor.java: TestFor.java

public class TestFor{public static void main(String[]args){

int i = 50;for (int i = 1;i >= 100; i++) // Error

System.out.println(“Hello World”);

}}

การประกาศตัวแปรนับจํานวนลูปในคําส่ัง for สามารถทําไดมากกวาหนี่งตัวโดยคั่นดวยเครื่องหมายจุลภาค และจะนํามาใชหรือไมก็ได ตัวอยางเชน

for (int i = 1, j= 2; i < 100; i++)

ถาทุกสวนในวงเล็บเปนเพียงความวางเปลา โปรแกรมจะวนลูป for โดยไมมีวันส้ินสุดเชน

โปรโปรโปรโปรแกรม แกรม แกรม แกรม 7 7 7 7 ---- 8 8 8 8 : TestFor.java: TestFor.java: TestFor.java: TestFor.java

public class TestFor{public static void main(String[]args){

for (;;)System.out.println(“Hello World”);

}}

Page 59: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 7 บล็อควนลูป

59

เคล็ดลับ ถาคุณอยากรูวารหัสยูนิโคดสากลแตละตัวมีคาเปนเทาไรบาง คุณสามารถดูไดจากการรันโปรแกรมขางลางน้ี

public class ShowUnicode{public static void main(String[]args){

char c = 0;for (int i =0; i <128 ; i++) {

c = (char) i;System.out.println(i + ’=’ + c);

}}

}

อยาลืมตั้งชื่อซอรสโคดวา ShowUnicode.java

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

คําส่ัง breakเราสามารถใชคําส่ัง break ในการบอกใหโปรแกรมออกจากลูปกระทันหันไดซึ่งใชไดทั้งลูป while และ for ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 7 7 7 7 ---- 9 9 9 9 : TestBreak.java: TestBreak.java: TestBreak.java: TestBreak.java

public class TestBreak{public static void main(String[]args){

int i = 1;while (i <= 10)

System.out.println(i + “ :Hello World”);if (i == 4) break;i++;

}}

Page 60: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 7 บล็อควนลูป

60

แทนที่โปรแกรมจะพิมพคําวา Hello World ออกหนาจอ 10 คร้ัง มันจะพิมพเพียง 4 คร้ัง เพราะเม่ือวนลูปคร้ังท่ีส่ี เง่ือนไขในวงเล็บหลังคําส่ัง if จะมีคาเปนจริง เปนผลทําใหคําส่ัง break ทํางาน ซึ่งก็คือโปรแกรมจะกระโดดออกจากลูป while กระทันหัน โดยไมสนใจคําสั่งที่ตามหลังคําสั่ง break ในลูป

คําส่ัง continueคําส่ัง continue คลายกับคําส่ัง break เพียงแตแทนที่จะหนีออกจากลูปอยางถาวร มันจะทิ้งคําสั่งในลูปที่ตามหลังมันมาเพียงครั้งเดียว แลววนลูปครั้งใหมโดยเริ่มที่ตนลูปใหม ตราบใดที่เงื่อนไขของลูปยังเปนจริง ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 7 7 7 7 ---- 10 10 10 10 : TestContinue.java: TestContinue.java: TestContinue.java: TestContinue.java

public class TestContinue {public static void main(String[] args){

for (int i = 1; i <= 10; i++) {if (i == 4) continue;System.out.println(i +“ : Hello World”);

}}

}

โปรแกรมนี้จะพิมพคําวา Hello World แคเกาคร้ัง โดยจะขามครั้งที่สี่ไป เพราะในการวนลูปคร้ังท่ีส่ี เง่ือนไขหลังคําส่ัง if จะเปนจริง ทําใหโปรแกรมกระโดดขามคําสั่งที่ตามมาในลูปในครั้งที่สี่แลวกลับมาวนลูปครั้งที่หาตอไปโดยเริ่มจากตนลูป โปรแกรมจึงไมพิมพคําวา Hello World ในคร้ังท่ีส่ีเทาน้ัน

Page 61: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

8 คลาสและวัตถุ

ท่ีผานมาเราเขียนโปรแกรมดวยการสรางคลาสข้ึนมาหน่ึงคลาสช่ือเดียวกับช่ือซอรสโคด ภายในคลาสมีแมธธอสหนึ่งแมธธอสชื่อ main และถาเราตองการใหโปรแกรมทําอะไรเราก็เอาคําส่ังเหลาน้ันใสเขาไปในสวนตัวของแมธธอส main โปรแกรมจะเริ่มรันจากคําสั่งแรกไปเรื่อย ๆจนจบคําส่ังสุดทาย โปรแกรมที่มีความซับซอนมากขึ้นจะมีคลาสมากกวาหนึ่งคลาส และคลาสเหลาน้ันไมตองมีช่ือเหมือนช่ือของไฟลซอรสโคด แตละคลาสก็อาจมีแมธธอสมากกวาหนึ่งแมธธอสไดดวย

จาวาเปนภาษาเชิงวัตถุ ทุกสิ่งทุกอยางภาษาจาวาจึงมีลักษณะเปนวัตถุ สิ่งที่เราใชในการนิยามวัตถุเรียกวา คลาส ซอรสโคดภาษาจาวา คือ คลาสตั้งแตหนึ่งคลาสขึ้นไปเขียนรวม ๆกันอยูในไฟล ๆเดียวน้ันเอง

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

ในบทนี้เราจะปูพื้นฐานเกี่ยวกับคลาสและวัตถุในภาษาจาวา อันเปนพ้ืนฐานท่ีสําคัญมากสําหรับการเรียนรูภาษาจาวาในระดับตอไป เพราะทุกสิ่งทุกอยางในภาษาจาวาเปนวัตถุ

Page 62: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 8 คลาสและวัตถุ

62

คลาสคลาส คือ นิยามของวัตถุ ดังที่ไดเกริ่นนําไปแลววาทุกสิ่งทุกอยางในภาษาจาวาเปนวัตถุ ดังน้ันการเขียนโปรแกรมภาษาจาวาจริง ๆแลวก็คือการเขียนคลาสตอ ๆ กันไปเร่ือย ๆน้ันเอง จาวาเวอรชัวนแมทชีนจะอานนิยามของวัตถุที่อยูในคลาสแลวสรางวัตถุขึ้นมา เพื่อทําใหไดผลลัพธเปนสิ่งที่ผูเขียนโปรแกรมตองการ

การเขียนโปรแกรมเชิงวัตถุโดยทั่วไปจะเริ่มจากการออกแบบวัตถุกอน ซึ่งสวนใหญแลวเรามักสรางวัตถุเลียนแบบวัตถุที่มีอยูจริง ๆ ในโลก ความยากอยูที่วาทําอยางไรวัตถุที่เราออกแบบนั้นจะทําใหโปรแกรมของเราทํางานอยางท่ีเราตองการได

การสรางวัตถุในโปรแกรมเชงิวัตถุ ทําไดดวยการนิยามวัตถุน้ันหรือการเขียนคลาสน้ันเอง รายละเอียดของคลาสคือสวนที่บอกวา วัตถุที่เราออกแบบตองมีคุณสมบัติ หรือพฤติกรรมอะไรบาง

เพื่อใหเขาใจมากขึ้นลองนึกถึงคําวา รถยนต ทําไมเวลาเราส่ือสารกับคนอ่ืนพอเราพูดคําวา รถยนต ทุกคนก็เขาใจเปนอยางเดียวกันกวา รถยนต หมายถึงอะไร การที่ทุกคนเขาใจเปนเพราะมีอะไรบางอยางที่ใชเปนเครื่องตัดสินวาสิ่งไหนที่เรียกวารถยนต และเคร่ืองตัดสินเหลาน้ีเปนท่ีเขาใจตรงกัน วัตถุชิ้นไหนไมมีสิ่งเหลานี้ก็ไมจัดเปนรถยนต ตัวอยางเชน ทุกคนถือวารถยนตตองมีลอ ตองมีเคร่ือง และตองวิ่งได

รถยนตเปนวัตถุ และการสรางคลาสรถยนตคือการบอกวาวัตถุท่ีจัดวาเปนรถยนตจะตองมีคุณลักษณะอะไรบาง แมวารถยนตจะมีรูปแบบหลากหลาย บางคันเล็ก บางคันใหญ บางคันมีสีแดง บางคันมีสีขาว บางคันวิ่งเร็ว บางคันวิ่งชา แตรถยนตทุกคันตองมีลักษณะรวมกันบางประการ ที่แน ๆก็คือ มีลอ มีเคร่ือง และ วิ่งได

ถาสังเกตใหดีจะเห็นวาสิ่งที่ใชบอกความเปนรถยนตหรือวัตถุใด ๆจะมีอยูสองลักษณะคือ บอกวาวัตถุตองมีอะไร (ในกรณีของรถยนตก็คือ ลอ และเคร่ือง) และบอกวาวัตถุตองทําอะไรได (ในกรณีของรถยนตไดแก วิ่งได)

เราเรียกสิ่งที่วัตถุหนึ่ง ๆตอง “มี” วา คุณสมบัติของวัตถุ และเรียกสิ่งที่วัตถุหนึ่ง ๆตอง ”ทํา” ไดวา พฤติกรรมของวัตถุ คุณสมบัติของวัตถุในภาษาจาวาแทนดวย ตัวแปรคลาส สวนพฤติกรรมของวัตถุในภาษาแทนดวยแมธธอส

การนิยามคลาสจึงไดแกการระบุ ตัวแปร และ แมธธอส น้ันเอง บางทีเราอาจกลาววาคลาสประกอบดวย ตัวแปรคลาส และแมธธอส หรือกลาววา ตัวแปรคลาส และแมธธอส คือ สมาชิกของคลาส

ตัวอยางในการเขียนคลาสของรถยนตในภาษาจาวาอาจมีรูปแบบดงนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 8 8 8 8 ---- 1 1 1 1 : Vehicle.java: Vehicle.java: Vehicle.java: Vehicle.java

class Vehicle { // (1)

int numberOfWheels; // (2)

Page 63: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 8 คลาสและวัตถุ

63

boolean hasEngine; // (3)

void run(){ // (4)System.out.println(“I am running”); // (5)

} // (6)

} // (7)

โปรแกรม Vehicle.java คอมไพลไดแตรันไมได ตอนนี้ยังไมขออธิบายวาทําไมจึงรันไมได ขอใหสนใจแตเรื่องรูปแบบของคําส่ังในการสรางคลาสกอน

การสรางคลาสเร่ิมตนดวยคําส่ังวา class ตามดวยชื่อของคลาสซึ่งจะตั้งชื่ออะไรก็ได แตตองเปนไปตามกฏของการตั้งชื่อในภาษาจาวาดังที่ไดเคยอธิบายไปแลวตอนที่เราตั้งชื่อของตัวแปร

ชื่อของคลาสตองขึ้นตนดวยตัวพิมพใหญเสมอ ถาประกอบดวยคําหลายคําตองเขียนติดกันใหเปนคําเดียวและนิยมใชตัวพิมพใหญขึ้นตนทุก ๆ ตัวอยางเชนชื่อตอไปนี้เปนชื่อคลาสที่ตั้งถูกหลักภาษาจาวาและถูกตองตามความนิยม

Lamp, Calculator, SwimmingPool, PetShopBoys

สิ่งที่อยูตามมาในคลาสจะถูกครอบดวยวงเล็บปกกา วงเล็บเปดอยูในบรรทัดเดียวกันกับช่ือของคลาส (1) สวนวงเล็บปดอยูในบรรทัด (7) เรานิยมวางวงเล็บไวในลักษณะน้ีเพ่ือความสะดวกในการมอง แตความจริงแลวการขึ้นบรรทัดใหมไมมีผลตอการคอมไพลโปรแกรมแตอยางใด

สิ่งที่อยูระหวางบรรทัด (1)และบรรทัด (7) คือรายละเอียดของคลาสซ่ึงไดแกการนิยาม ตัวแปร และ แมธธอส น้ันเอง เรานิยมยอหนาเนื้อหาทั้งหมดในคลาสใหหลบเขาไปหนึ่งขั้นเพื่อความสะดวกในการมอง คลาสรถยนตประกอบดวยตัวแปรคลาสสองตัว และแมธธอสหนึ่งแมธธอส ดังในภาพ

รูปที่ รูปที่ รูปที่ รูปที่ 8888----1111 คลาสรถยนตคลาสรถยนตคลาสรถยนตคลาสรถยนต

บรรทัด (2) คือการประกาศตัวแปรคลาสช่ือ numberOfWheels ซึ่งเปนตวแปรแบบ int ตัวแปร numberOfWheels จะมีไวเก็บจํานวนลอของรถ เพราะเราแนใจวารถยนตมีลอแน ๆ แตรถยนตแตละชนิดอาจมีลอไมเทากัน

Page 64: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 8 คลาสและวัตถุ

64

บรรทัด (3) คือการประกาศตัวแปรคลาสตัวท่ีสองช่ือ hasEngine ซึ่งเปนตัวแปรแบบ boolean ตัวแปรhasEngine มีไวบอกวารถยนตมีเครื่องหรือไม (ดวยสามัญสํานึกคุณคงนึกออกวาตัวแปร hasEngine ควรมีคาเปนจริงเสมอ เพราะรถยนตตองมีเคร่ือง)

บรรทัด (4) (5) และ (6) เปนการประกาศแมธธอส การประกาศแมธธอสเริ่มตนดวย คําวา void ตามดวยชื่อของแมธธอส ซึ่งเปนชื่ออะไรก็ไดที่เปนไปตามกฏการตั้งชื่อของภาษาจาวา ชื่อแมธธอสตองลงทายดวยเครื่องหมาย () เสมอ เชนในกรณีนี้เมททอสนี้มีชื่อวา run() การตั้งชื่อเมททอสนิยมขึ้นตนดวยอักษรตัวพิมพเล็ก และถาประกอบดวยคําหลายคําจะเขียนติดกันหมดและใชตัวพิมพใหญขึ้นตนคําทุกคําที่ตามมา เชนเดียวกับการตั้งชื่อตัวแปรทุกประการ

สิ่งที่อยูหลังชื่อของแมธธอสคือบลอคปกกาซึ่งอธิบายพฤติกรรม run() หรือสวนตัวของแมธธอสน้ันเอง ภายในบลอคปกกาเราใชคําส่ังในภาษาจาวาเขียนตอกันไปเร่ือย ๆเพื่ออธิบายพฤติกรรมการวิ่ง ตัวอยางเชน ในกรณีน้ี พฤติกรรม run() คืออาการท่ีรถยนตว่ิงได ซึ่งเราแทนดวยการแสดงผลที่หนาจอวา I am running และเชนเคยเรานิยมยอหนาคําสั่งทั้งหมดในบลอคปกกาใหลึกกวาวงเล็บปกกาเอง เพ่ือความสะดวกในการมอง

กลับมามองโปรแกรมภาษาจาวาที่เราเคยเขียนมากอนในอดีต โปรแกรมภาษาวาจาเหลานั้นลวนมีโครงสรางพื้นฐานเปนดังน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 8888 ---- 2222 : HelloWorld.java: HelloWorld.java: HelloWorld.java: HelloWorld.java

public class HelloWorld {public static void main ( String [] args ) {

}}

น้ันคือท่ีผานมาโปรแกรมของเราประกอบดวยคลาสหน่ึงคลาสท่ีมีช่ือเหมือนชื่อโปรแกรม คลาสคลาสน้ีไมมีตัวแปรคลาสเปนสมาชิก และมีแมธธอสแคหนึ่งแมธธอส ชื่อวา main() (อยาเพิ่งสนใจคําวา public static หรือString[] args) การการเขียนโปรแกรมในภาษาจาวาแทที่จริงก็คือการเขียนนิยามของ class น้ันเอง

Page 65: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 8 คลาสและวัตถุ

65

รูปที่รูปที่รูปที่รูปที่ 8 8 8 8----2222 คลาส คลาส คลาส คลาส HelloWorldHelloWorldHelloWorldHelloWorld

โปรแกรมในภาษาจาวาที่สามารถรันไดตองมีคลาสอยางนอยหนึ่งคลาสที่มีชื่อเหมือนชื่อของซอรสโคด และในคลาสนั้นตองมีแมธธอสชื่อ main() จาวาเวอรชัวนแมทชีนจะมองหาแมธธอสชื่อนี้เสมอทุกครั้งที่รัน เพราะมันจะใชแมธธอส main() เปนจุดเร่ิมตนของการรัน นี่เปนเหตุผลที่ทําไมคลาสรถยนตของเราจึงคอมไพลไดแตรันไมได และที่ผานมาเราเขียนโปรแกรมใหสั้นที่สุดแตพอรันไดดวยการใหมีแคคลาสเดียวชื่อเหมือนชื่อโปรแกรม และมีแมธธอสชื่อ main() โปรแกรมท่ีใหญและซับซอนกวาน้ีอาจมีคลาสเปนรอย ๆคลาสในซอรสโคด

วัตถุวัตถุ คือ สิ่งที่มีคุณสมบัติและพฤติกรรมตามที่กําหนดไวในคลาส วัตถุของคลาสรถยนตก็คือตัวรถยนต คลาสเปนแคคํานิยามไมมีตัวตนอยูจริง สิ่งที่มีตัวตนอยูจริงคือ วัตถุ

คลาสรถยนตมีไดแคคลาสเดียว เพราะ ถานิยามของคําวารถยนตมีไดหลายนิยามเวลาสนทนาเรื่องรถยนตคงสับสนวุนวายนาดู แตรถยนตที่เปนวัตถุมีไดหลายคัน ในกรุงเทพจังหวัดเดียวมีรถยนตมากกวาหนึ่งลานคัน ในโปรแกรมภาษาจาวาโปรแกรมหนึ่ง จะมีคลาส Vehicle ไดคลาสเดียวแตมีวัตถุรถยนตไดหลายวัตถุ วัตถุในภาษาจาวาเรียกวา อินสแตนท

การสรางวัตถุเราเรียกวา การสรางอินสแตนท ใหกับคลาส ดังนั้นบางทีเราก็เรียกวัตถุวา อินสแตนทของคลาส ดวย ในหนังสือเลมนี้เราจะเรียกวัตถุวา อินสแตนท เปนหลัก ขอใหระลึกไววาคือสิ่งเดียวกัน

ตัวอยางของการสรางอินสแตนทใหกับคลาสรถยนตเปนดังตอไปน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 8 8 8 8 ---- 3 3 3 3 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;void run(){

System.out.println(“I am running.”);}

Page 66: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 8 คลาสและวัตถุ

66

}

public class BuildACar {public static void main (String[] args) {

new Vehicle(); // (1)new Vehicle(); // (2)System.out.println(“Two cars have been built.”);

}}

โปรแกรม BuildACar.java มีสองคลาส คลาสแรกคือคลาสรถยนต คลาสท่ีสองคือคลาส BuildACar ซึ่งมีชื่อเหมือนชื่อโปรแกรม คลาสน้ีเปนคลาสหลักของโปรแกรม เพราะมีแมธธอส main() อยู

อันท่ีจริง ลําดับของคลาสในไฟลจะเรียงลําดับอยางไรก็ได เราอาจเขียนคลาส BuildACar อยูกอนคลาส Vehicle ก็ได

ส่ิงท่ีนาสนใจอยางหน่ึงก็คือถาลองคอมไพลโปรแกรม BuildACar.java เราจะไดไฟลนามสกุล .class ถึงสองไฟลคือ BuildACar.class และ Vehicle.class น้ันคือในกรณีท่ีซอรสโคดของเราประกอบดวยคลาสมากกวาหนึ่งคลาส เมื่อนํามาคอมไพลจะไดไฟล .class หนึ่งไฟลสําหรับทุก ๆคลาสในซอรสโคด แยกเปนอิสระจากกัน ไฟลนามสกุล .class ทุกไฟลมีความสําคัญตอการรันโปรแกรมทั้งสิ้น จาวาเวอรชัวนแมทชีนจะตองเห็นไฟล .class ครบทุกไฟลมิฉะนั้นโปรแกรมจะรันไมได

โปรแกรมนี้เริ่มตนที่แมธธอส main() คําส่ังในบรรทัด (1) (2) คือคําส่ังสรางอินสแตนทใหกับคลาส Vehicle หรือก็คือการสรางรถยนต น้ันเอง เราใชคําส่ัง new ตามดวยชื่อคลาส โดยมีเครื่องหมาย () ปดทายในการสรางอินสแตนทของคลาสน้ัน ๆ ในโปรแกรมน้ีเราส่ังสองที ดังน้ันเราจะไดรถยนตสองคัน

เวลารันโปรแกรมน้ีบนจาวาเวอรชัวนแมทชีน จาวาเวอรชัวนแมทชีนจะอานนิยามของคลาสทุกคลาสที่มีอยูในไฟล .class แลวลอกนิยามเหลาน้ันลงบนแรม ซ่ึงคลาสหน่ึง ๆจะถูกลอกลงบนแรมเพียงคร้ังเดียวเทาน้ันตอนเร่ิมโปรแกรม บางทีเราเรียกชวงเวลาที่จาวาเวอรชัวนแมทชีนกําลังลอกนิยามของคลาสลงบนแรมวา ชวงโหลดโปรแกรม น้ันเอง ในกรณีน้ีมันจะโหลดเน้ือหาของคลาส Vehicle และ BuildACar เขาไปในแรม

หลังจากโหลดโปรแกรมเสร็จโปรแกรมจะเริ่มรันจากแมธธอส main() ในกรณีนี้แมธธอส main() เร่ิมดวยคําส่ังสรางอินสแตนทของคลาส Vehicle สองอินสแตนท จาวาเวอรชัวนแมทชีนจะกันเนื้อที่ใหมในแรมไวใหกับอินสแตนทแตละอินสแตนท แลวสรางเปนท่ีเก็บตัวแปรคลาส และแมธธอส ของแตละอินสแตนท คลาสเดียวกันสามารถถูกสรางอินสแตนทไดหลาย ๆอินสแตนทตามชอบใจ จาวาเวอรชัวนแมทชีนจะกันเนื้อที่ในแรมใหมใหกับอินสแตนทหใหมทุกอินสแตนทที่สรางขึ้น โดยไมมีการแบงใชเนื้อที่รวมกัน

Page 67: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 8 คลาสและวัตถุ

67

อินสแตนทที่ถูกสรางขึ้นจะอยูในแรม ตอนนี้เราไมสามารถนํามันมาใชงานไดเพราะเราไมรูจะอางถึงมันอยางไร การอางถึงอินสแตนทในแรมเพ่ือเอาอินสแตนทมาใชงานเราอาศัยตัวแปรพิเศษชนิดหนึ่งที่เรียกวา ตัวแปรอางอิง

Page 68: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม
Page 69: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

9 ตัวแปรอางอิง

ตัวแปรอางอิง คือ ตัวแปรที่ใชเก็บเลขบอกตําแหนงในแรม ตําแหนงในแรมเหลานั้นอาจเปนที่อยูของอินสแตนทที่เราสรางขึ้นมา เวลาท่ีเราตองการอางถึงอินสแตนทน้ันเราจะใชการอางถึงตัวแปรอางอิงที่เก็บเลขบอกตําแหนงที่อยูของอินสแตนทน้ันแทน หรืออีกนัยหนึ่งตัวแปรอางอิงก็คือตัวชี้อินสแตนทนั้นเอง

ตัวแปรอางอิงไมมีช่ือ่เรียกเฉพาะของมนัเอง ชื่อของมันเปลี่ยนไปเรื่อยตามชื่อคลาสของอินสแตนทที่มันชี้อยู ลองดูตัอยางการประกาศตัวแปรอางอิงที่ใชชี้อินสแตนทรถยนตที่เราสรางขึ้นเมื่อบทที่แลวดูดังตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 9 9 9 9 ---- 1 1 1 1 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;void run(){

System.out.println(“I am running”);}

}

public class BuildACar {public static void main (String[] args) {

Vehicle myCar,yourCar; // (1)myCar = new Vehicle(); // (2)yourCar = new Vehicle(); // (3)System.out.println(myCar); // (4)

Page 70: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 9 ตัวแปรอางอิง

70

System.out.println(yourCar); // (5)}

}

ในบรรทัด (1) เราประกาศตัวแปรอางอิงสองตัวชื่อ myCar และ yourCar ชื่อชนิดของตัวแปรอางอิงเหมือนชื่อคลาส Vehicle เพราะเราตองการใหมันใชชีอิ้นสแตนทของคลาส Vehicle ได ถาตองการตัวแปรอางอิงไวใชอินสแตนทคลาสอ่ืน ก็ใชช่ือคลาสน้ัน ๆแทนในการประกาศ

ในบรรทัด (2) (3) เราสรางอินสแตนทของคลาส Vehicle ขึ้นแลวกําหนดใหคาของตัวแปร myCar และ yourCar มีคาเทากับเลขชี้ตําแหนงของอินสแตนททั้งสองในแรม

ในบรรทัด (4) (5) เราลองแสดงคาของ myCar และ yourCar ออกนอกจอดู ผลการรันโปรแกรมน้ีอาจเปนดังภาพขางลาง

จะเห็นไดวา myCar และ yourCar มีคาเปนตัวเลขฐานสิบหก เลขฐานสิบหก นี้คือตําแหนงในแรมที่อินสแตนทที่สรางข้ึนอยู สวนคําวา Vehicle@ เปนเพียงการกํากับวาอินสแตนทน้ีเปนอินสแตนทของคลาส Vehicle เฉย ๆ

รูปที่รูปที่รูปที่รูปที่ 9 9 9 9----1 1 1 1 ตําแหนงของอินสแตนทในแรมตําแหนงของอินสแตนทในแรมตําแหนงของอินสแตนทในแรมตําแหนงของอินสแตนทในแรม

C:\java> java BuildACarVehicle@1111f71Vehicle@2373f3d

Page 71: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 9 ตัวแปรอางอิง

71

ตําแหนงในแรมนี้จาวาเวอรชัวนแมทชีนเปนคนเลือกให ซ่ึงอาจไมเทากันในการรันแตละคร้ัง เราไมมีสิทธิ์เลือกตามใจเรา

คําส่ังประกาศตัวแปรอางอิง และคําส่ังสรางอินสแตนทสามารถยุบรวมเปนคําส่ังเดียวกันไดดวย เชนVehicle myCar = new Vehicle();Vehicle yourCar = new Vehicle();

ตอไปน้ีเราจะใชคําส่ังในรูปแบบน้ีเปนหลักเพราะกระทัดรัดกวา

เน่ืองจากเราใชช่ือคลาสในการประกาศตัวแปรอางอิง และคําสั่งก็มีรูปแบบเหมือนการประกาศตัวแปรพื้นฐานแบบอื่น ๆ ดังน้ันบางทีเราอาจกลาววา myCar และ yourCar เปนตัวแปรชนิด Vehicle หรือบอยคร้ังเราอาจเรียก myCar หรือ yourCar วาเปนอินสแตนทของคลาส Vehicle ไดดวย แตขอใหระลึกไววามันคือตัวแปรอางอิงที่ใชชี้อินสแตนทของคลาส Vehicle มิใชตัวอินสแตนทของคลาส Vehicle ตัวแปรอางอิงไมไดผูกติดกับอินสแตนทที่มันชี้อยูตลอดไป มันอาจเปล่ียนไปช้ีอินสแตนทอ่ืนไดดวย ลงพิจารณาตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 9 9 9 9 ---- 2 2 2 2 : Reference.java

class Vehicle {

int numberOfWheels;boolean hasEngine;void run(){

System.out.println(“I am running”);}

}

public class Reference {public static void main (String[] args) {

Vehicle myCar = new Vehicle();Vehicle yourCar = new Vehicle();System.out.println(“myCar points to “ + myCar);System.out.println(“yourCar points to “ + yourCar);

yourCar = myCar; // (1)System.out.println(“yourCar now points to “ + yourCar);myCar = null; // (2)System.out.println(“myCar points to “ + myCar);

}}

Page 72: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 9 ตัวแปรอางอิง

72

ผลของการรันโปรแกรมเปนดังภาพ

โปรแกรมเริ่มตนดวยการสรางตัวแปรอางอิง myCar และ yourCar ซึ่งกําหนดใหชี้ไปยังอินสแตนทของ Vehicle ที่ตําแหนง 111f71 และ 273d3c ตามลําดับ

ในบรรทัด (1) มีการกําหนดคาใหมใหตัวแปรอางอิง yourCar มีคาเทากับคาปจจุบันของ myCar คือ 111f71ผลท่ีไดคือตัวแปรอางอิง yourCar จะชี้ไปยังอินสแตนทเดียวกับ myCar ดังภาพ

รูปที่รูปที่รูปที่รูปที่ 9999----2222ตําแหนงในแรมตําแหนงในแรมตําแหนงในแรมตําแหนงในแรม

เราสามารถทําใหตัวแปรอางอิงไมชี้อะไรเลยไดดวยการกําหนดคาของตัวแปรอางอิงใหเทากับ null ในบรรทัด (2) เรากําหนดคา null ใหตัวแปร myCar ตอนนี้ตัวแปรอางอิง myCar ไมช้ีอินสแตนทอะไรเลย

C:\java> java ReferencemyCar points to Vehicle@111f71yourCar points to Vehicle@273d3cyourCar points to Vehicle@111f71myCar points to null

Page 73: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 9 ตัวแปรอางอิง

73

รูปที่รูปที่รูปที่รูปที่ 9 9 9 9————3 3 3 3 ตําแหนงในแรมตําแหนงในแรมตําแหนงในแรมตําแหนงในแรม

null เปนคําเฉพาะในภาษาจาวาและตองเขียนดวยตัวพิมพเล็กเทานั้น

ปกติเวลาสรางอินสแตนทใหมขึ้นมาเราก็จะประกาศตัวแปรอางอิงขึ้นมาชี้ดวยเสมอ อินสแตนทที่ไมมีตัวแปรอางอิงใดช้ีอยูจะเส่ียงตอการถูกทําลาย ตัวอยางเชน อินสแตนทท่ีเราสรางข้ึนมาเฉย ๆโดยไมกําหนดตัวแปรอางอิงให หรืออินสแตนทที่เคยมีตัวแปรอางอิงแตเราจับตัวแปรอางอิงนั้นใหเทากับ null เสีย ทุกระยะของการรันโปรแกรม จาวาเวอรชัวนแมทชีนจะตรวจสอบดูวามีอินสแตนทใดบางที่เขาขายนี้ มันจะทําลายอินสแตนทเหลานั้นเสียเพื่อคืนแรมใหกับระบบ เราไมสามารถทํานายพฤติกรรมการทําลายของจาวาเวอรชัวนแมทชีนได บางครั้งมันลุกขึ้นมาตรวจสอบมันแลวพบอินสแตนทที่เขาขายมันอาจจะทําลายหรือไมทําลายก็ได แตขอดีก็คือ หนาที่การทําลายอินสแตนทเปนของจาวาเวอรชัวนแมทชีน นักเขียนโปรแกรมไมตองสนใจ

เคล็ดลับ เวลาศึกษาเร่ืองคลาสและวัตถุ ควรใหความสําคัญกับเรื่องของการใชเนื้อที่ในแรม เพราะจะทําใหเขาใจไดดียิ่งขึ้น แมวาการจัดการแรมจะเปนหนาที่ของจาวาเวอรชัวนแมทชีนก็ตาม

Page 74: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม
Page 75: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

10 ตัวแปรคลาส

คลาส Vehicle มีตัวแปรคลาสสองตัวเปนสมาชิกคือ numberOfWheels และ hasEngine ตัวแปรคลาสมีไวแสดงคุณสมบัติของวัตถุ

ตัวแปรคลาสจะมีกี่ตัวก็ได และจะเปนตัวแปรชนิดใดก็ได ตั้งแตตัวแปรพื้นฐานจนถึงตัวแปรอางอิง ที่ผานมาจะเห็นไดวาเราประกาศตัวแปรคลาสไวเฉย ๆในคลาสโดยไมมีการกําหนดคาให ที่จริงแลวเราสามารถกําหนดคาของตัวแปรคลาสไวในคลาสไดดวย เชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 10 10 10 10 ---- 1 1 1 1 : Vehicle.java: Vehicle.java: Vehicle.java: Vehicle.java

class Vehicle {

int numberOfWheels = 4;boolean hasEngine = true;void run(){

System.out.println(“I am running”);}

}

Page 76: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 10 ตัวแปรคลาส

76

คาที่เรากําหนดใหจะเปนคาเริ่มตนของตัวแปรนั้น ๆตอนที่มีการสรางอินสแตนทของวัตถุนั้นขึ้น แตถาไมกําหนดคาไวในคลาส จาวาเวอรชวันแมทชนีจะกําหนดคาใหเอง คาที่กําหนดใหเราเรียกวา คาปกติของตัวแปรคลาส มีดังน้ี

ตารางที่ตารางที่ตารางที่ตารางที่ 10101010----1111 คาปกติของตัคาปกติของตัคาปกติของตัคาปกติของตัวแปรคลาส วแปรคลาส วแปรคลาส วแปรคลาส

ชนิดตัวของแปร คาปกติ ตัวแปรตัวเลข 0 ตัวแปรตรรก false ตัวแปรตัวอักษร \u0000 ตัวแปรอางอิง null

ตัวแปรคลาสประกาศไวในคลาส และไมเหมือนกับตัวแปรที่ผาน ๆมาตอนท่ีเรียนเร่ืองตัวแปรพ้ืนฐาน ตัวแปรเหลานั้นประกาศและใชงานภายในแมธธอส ตัวแปรที่เราประกาศไวในแมธธอสเราเรียกวา ตัวแปรทองถ่ิน

ตัวแปรทองถิ่นไมมีคาปกติ จึงไมปลอดภัยเหมือนตัวแปรคลาส เพราะถาเราประกาศตัวแปรทองถิ่นไวเฉย ๆ โดยไมไดกําหนดคาไว โปรแกรมจะหยุดชะงักถามีการเอาตัวแปรทองถิ่นตัวนั้นไปใชงาน เชน

โปรแกรโปรแกรโปรแกรโปรแกรม ม ม ม 11110 0 0 0 ---- 2: TestVariable.java 2: TestVariable.java 2: TestVariable.java 2: TestVariable.java

public class TestVariable {public static void main(String[]args){

char c;System.out.println(c); // (1) Error

}}

ถารันโปรแกรมนี้โปรแกรมจะหยุดชะงักที่บรรทัด (1) เพราะมันไมรูวาตัวแปร c มีคาเปนเทาไหร

สรุปก็คือ เวลาประกาศตัวแปรคลาสจะกําหนดคาเร่ิมตนหรือไมก็ได เพราะถาไมกําหนดจาวาเวอรชัวนแมทชีนจะกําหนดคาปกติให แตในกรณีของตัวแปรทองถิ่นควรกําหนดคาเริ่มตนทันทีที่ประกาศเพื่อปองกันโปรแกรมหยุดชะงักโดยไมตั้งใจ

ตัวแปรคลาสท่ีเห็นในคลาสเปนเพียงแคนิยามทาน้ัน ตัวแปรคลาสจะเกิดขึ้นจริง ๆก็ตอเมือ่มีการสรางอินสแตนทของคลาสขึ้นมาใชงาน ที่อยูของตัวแปรคลาสจะอยูในที่วางในแรมที่กันไวใหสําหรับอินสแตนทนั้น ๆ อินสแตนทแตละอินสแตนทที่สรางขึ้นจะมีตัวแปรคลาสเปนของมันเองหนึ่งชุด ไมมีการใชรวมกันขามอินสแตนท และตัวแปรคลาสจะตายไปพรอมกับอินสแตนทนั้น ๆ เวลาที่จาวาเวอรชัวนแมทชีนทําลายอินสแตนท

Page 77: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 10 ตัวแปรคลาส

77

สําหรับตัวแปรทองถิ่น จะเกิดขึ้นจริงก็ตอเมื่อมีการเรียกใชงานแมธธอสนั้น และจะตายทันทีที่แมธธอสรันเสร็จ ตัวแปรทองถิ่นถูกอางถึงไดเฉพาะภายในแมธธอสที่มันอยูเทานั้น ดังน้ันในคลาสเดียวกันช่ือของตัวแปรคลาส อาจซ้ํากับตัวแปรทองถิ่นบางตัวที่อยูในแมธธอสได ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 10 10 10 10 ---- 3 3 3 3 : TestClass.java: TestClass.java: TestClass.java: TestClass.java

class TestClass {

int i;

void x(){int i;

}

}

ยอนกลับไปดูโปรแกรม 9-1 ในบทที่แลว อินสแตนท myCar และ yourCar ตางก็มีตัวแปร numberOfWheels และ hasEngine เปนของตัวเอง ไมเกี่ยวของกันและไมจําเปนตองมีคาเทากัน รถยนตของผมอาจเปนรถบรรทุกมี 6 ลอ สวนรถยนตของคุณอาจเปนรถเกงมี 4 ลอ เราสามารถเปล่ียนคาของตัวแปรคลาสภายหลังได และการอางถึงตัวแปรคลาสเหลานั้นทําไดโดยใชชื่ออินสแตนทตามดวยจุดตามดวยชื่อตัวแปร ลองดูตัวอยางตอไปน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 10 10 10 10 ---- 4 4 4 4 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

class Vehicle {

int numberOfWheels = 4;boolean hasEngine = true;void run(){

System.out.println(“I am running”);}

}

public class BuildACar {public static void main (String[] args) {

Vehicle myCar = new Vehicle(); // (1)Vehicle yourCar = new Vehicle(); // (2)myCar.numberOfWheels = 6; // (3)yourCar.numberOfWheels = 4; // (4)System.out.println(“My car has “ + myCar.numberOfWheels + “

wheels.”);

Page 78: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 10 ตัวแปรคลาส

78

System.out.println(“Your car has “ + yourCar.numberOfWheels + “wheels.”);}

}

ลองคอมไพลและรันโปรแกรมขางตนจะไดผลเปนดังน้ี

บรรทัด (1) (2) เปนการสรางอินสแตนทสองอินสแตนทช่ือ myCar และ yourCar ตามลําดับ แตละอินสแตนทจะเปนอิสระจากกันและอยูคนละท่ีในแรม แตละอินสแตนทจะมีตัวแปรอินสแตนท numberOfWheels และ hasEngine ของตัวเองแถมมาใหทันทีที่อินสแตนทถูกสรางขึ้นโดยที่เราไมจําเปนตองสราง คาเร่ิมตนของ numberOfWheels จะเปน 0 สวน hasEngine จะเปนเท็จ เพราะเปนคาปกติของตัวแปรคลาส

บรรทัด (3) และ (4) เปนการกําหนดคาใหกับตัวแปรอินสแตนท numberOfWheels ของอินสแตนทท้ังสอง เราใชชื่อตัวแปรอางอิงตามดวยจุดนําหนาชื่อตัวแปร เพื่อแยกแยะความแตกตางวาเปนตัวแปรของอินสแตนทไหน จากนั้นโปรแกรมจะแสดงคาของตัวแปรทั้งสองออกหนาจอ สังเกตวาคาของตัวแปรอินสแตนทเปนของใครของมัน และไมจําเปนตองมีคาเทากัน

ตัวแปรสแตรติกเราสามารถสรางตัวแปรคลาสท่ีเปนของคลาสเองจริง ๆ ไมมีอินสแตนทใดยึดความเปนเจาของ แตเปนของกลางที่อินสแตนททุกอินสแตนทของคลาสแบงกันใช เราเรียกตัวแปรคลาสน้ีวา ตัวแปรสแตรติก ซึ่งประกาศไดโดยการใชคําส่ัง static ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 10 10 10 10 ---- 4 4 4 4 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

class Vehicle {

int numberOfWheels ;boolean hasEngine ;static int numberOfCars; // (1)

void run(){System.out.println(“I am running”);

}

C:\java> java BuildACarMy car has 6 wheels.Your car has 4 wheels.

Page 79: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 10 ตัวแปรคลาส

79

}

public class BuildACar {public static void main (String[] args) {

Vehicle myCar = new Vehicle();myCar.numberOfCars++;// (2)myCar.numberOfWheels = 6;

Vehicle yourCar = new Vehicle();yourCar.numberOfCars++;// (3)yourCar.numberOfWheels = 4;System.out.println(“My car has “ + myCar.numberOfWheels + “

wheels.”);System.out.println(“Your car has “ + yourCar.numberOfWheels + “

wheels.”);System.out.println(“There are “ + Vehicle.numberOfCars + “ cars

in the world.”); // (4)}

}

ผลการรันโปรแกรมเปนดังน้ี

ในโปรแกรมน้ีคลาส Vehicle มีตัวแปรคลาสเพิ่มขึ้นหนึ่งตัวคือ numberOfCars ในบรรทัด (1) ตัวแปรตัวนี้ประกาศใหเปนตัวแปรสแตรติก ซึ่งใชนับจํานวนรถยนตที่ผลิตขึ้น

ทุกครั้งที่มีการสรางอินสแตนทใหคลาส Vehicle จะมีการเพิ่มคาของตัวแปร numberOfCars ทีละหนึ่งเชนในบรรทัด (2) และ (3)

เมือ่แสดงคาของ numberOfCars ออกท่ีหนาจอในบรรทัด (4) จะพบวามีคาเปน 2 เพราะท้ังคําส่ัง myCar.numberOfCars++ และ yourCar.numberOfCars++ ตางก็ไปเพิ่มคาตัวแปรตัวเดียวกันเพราะตัวแปรสแตรติกมีแคชุดเดียวตลอดการรันโปรแกรม ผลที่ไดคือตัวแปร numberOfCars มีคาเปน 2

การอางถึงตัวแปรสแตรติกจะใชชื่อของคลาสหรือชื่อของอินสแตนทก็ได ดังน้ัน myCar.numberOfCars,yourCar.numberOfCars และ Vehicle.numberOfCars คือตัวแปรตัวเดียวกันทั้งสิ้น

C:\java> java BuildACarMy car has 6 wheels.Your car has 4 wheels.There are 2 cars in the world.

Page 80: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 10 ตัวแปรคลาส

80

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

ตัวแปรถาวรเราสามารถสรางตัวแปรคลาสท่ีมีคาถาวรเปล่ึยนแปลงไมไดอีก ดวยการใชคําสั่ง final นําหนา เชน

final float PI = 3.14159;

ในตัวอยางเปนการกําหนดคาคงตัว PI ในวิชาเรขาคณิต ปกติแลวเรานิยมเปลี่ยนไปใชอักษรพิมพใหญทั้งหมดในการตั้งชื่อตัวแปรถาวร ทั้งที่เปนแคความนิยมเทานั้น

ตัวแปรถาวรตองมีการกําหนดคาดวย และการกําหนดคาทําไดแคคร้ังเดียว คาน้ีจะเปล่ียนไมดีอีกตลอดการรันโปรแกรม

ทั้งตัวแปรคลาสปกติและตัวแปรสแตรติกสามารถประกาศใหเปนตัวแปรถาวรได นอกจากน้ีตัวแปรทองถ่ินก็ประกาศใหเปนตัวแปรถาวรไดดวย

แตตัวแปรทองถิ่นประกาศใหเปนตัวแปรสแตรติกไมได

Page 81: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

11 อะเรย

อะเรย คือ เซตของตัวแปรชนิดเดียวกัน ซึ่งสมาชิกของอะเรยอาจเปนตัวแปรพื้นฐานหรือตัวแปรอางอิงก็ได จํานวนสมาชิกของอะเรยมีขนาดแนนอน และสมาชิกของอะเรยแตละตัวจะมีลําดับประจําตัวอยู

อะเรยในภาษาจาวาเปนวัตถุ ดังน้ันจึงเปนการดีท่ีจะกลาวถึงอะเรยในบทน้ี เพื่อจะไดเห็นตัวอยางของการเอาแนวคิดเรื่องวัตถุไปใชจริง อยางไรก็ตามอะเรยเปนวัตถุแบบพิเศษ จึงมีวิธีการใชงานและคําสั่งที่ไมเหมือนกับวัตถุทั่วไปนัก

เพราะอะเรยเปนวัตถุ ดังน้ันตองมีการประกาศตัวแปรอางอิง และสรางอินสแตนท

การประกาศอะเรยหรือการประกาศตัวแปรอางอิงแบบอะเรย ทําไดดังตัวอยาง

int[] i;int[] a, b;

คําส่ังขางตนเปนการประกาศอะเรยช่ือ i ซึ่งมีสมาชิกของอะเรยเปนตัวแปรประเภท int สมาชิกของอะเรยเดียวกันตองเปนตัวแปรประเภทเดียวกันเสมอ คําส่ังในการประกาศอะเรยใชสัญลักษณเคร่ืองหมายวงเล็บเหล่ียม ซ่ึงอาจวางอยูตอทายชื่อชนิดของตัวแปรสมาชิก หรือวางอยูตอทายชื่อตัวแปรอะเรยก็ไดดัง เชน

int i[];int a[], b[];int x[], y;

Page 82: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 11 อะเรย

82

ในกรณีที่เราวางวงเล็บไวตอทายชื่ออะเรย ตองวางไวทายชื่ออะเรยทุกตัวในบรรทัด มิฉะนั้นตัวที่ไมมีวงเล็บตอทายจะกลายเปนตัวแปรธรรมดาไป ตัวอยางขางตนตัวแปร y ไมใชอะเรยแตเปนตัวแปร int ธรรมดา

ข้ันตอนตอไปคือการกําหนดสรางตัวแปรอะเรย ซ่ึงก็คลาย ๆกับการสรางอินสแตนทของอะเรย แตคําสั่งอาจดูแตกตางกับการสรางอินสแตนทของวัตถุปกติเล็กนอย เชน

int[] nn = new n[10];

เราใชคําส่ัง new ในการสรางตัวแปรอะเรย และระบุจํานวนสมาชิกไวภายในวงเล็บกามปู อยางในกรณีน้ี อะเรย nจะมีสมาชิกเปนตัวแปรจํานวนเต็มจํานวนทั้งสิ้น 10 ตัวแปร เมื่อจาวาเวอรชัวนแมทชีนพบคําสั่งในการสรางอะเรย มันจะทําการกันเนื้อที่ไวใหในแรมสําหรับเก็บตัวแปรซึ่งในกรณีนี้คือ ตัวแปรแบบจํานวนเต็มสิบตัว เราอาจมอง nเปนวัตถุที่มีตัวแปรคลาส 10 ตัวเปนตัวแปร int ทั้งหมดก็ได

เราสามารถยุบคําส่ังในการประกาศ และคําส่ังในการสรางเปนคําส่ังเดียวไดดังตัวอยาง

int[] n = new n[10];

ตอไปน้ีเราจะใชรูปแบบคําส่ังแบบน้ีในการประกาศและสรางอะเรยเปนหลัก เพราะมคีวามกระชับกวา

เม่ือสรางตัวแปรอะเรยเสร็จแลวก็ถึงข้ันตอนของการกําหนดคา เราใชเครื่องหมายปกกาในการกําหนดคา คําส่ังในการกําหนดคาเปนคําส่ังท่ีรวมการประกาศ และการสรางเอาไวดวยเสมอ ไมมีคําสั่งกําหนดคาอยางเดียว

int[] b = { 1, 4, 12 ,2 , 1, 4 }

คําส่ังน้ีเปนท้ังการประกาศ การสราง และการกําหนดคาใหกับอะเรย b ในคําส่ังเดียว อะเรย b จะมีสมาชิกเปนตัวแปรจาํนวนเต็ม 6 ตัว มีคาของตัวแปรแตละตัวเปน 1, 4, 12, 2 , 1, 4 ตามลําดับ

ถาเราตองการอางถึงตัวแปรท่ีเปนสมาชิกของอะเรย เราใชสัญลักษณ b[0], b[1], b[2], b[3], b[4],

b[5] แทนสมาชิกตัวแรกจนถึงตัวสุดทายตามลําดับ สังเกตวาเลขดรรชนีเร่ิมจาก 0 เสมอ ดังน้ันสมาชิกตัวสุดทายของอะเรยจะมีเลขดรรชนีเทากับจํานวนสมาชิกทั้งหมดของอะเรยลบดวยหนึ่ง ตัวอยางการอางถึงก็เชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 11 11 11 11 ---- 1 1 1 1 : TestArray.java: TestArray.java: TestArray.java: TestArray.java

public class TestArray {public static void main (String[] args) {

int[] b = { 1, 4, 12 ,2 , 1, 4 }int k = b[0] + b[1];

}}

Page 83: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 11 อะเรย

83

อะเรยเปนวัตถุที่สามารถสรางไดทันทีโดยไมตองนิยามคลาสขึ้นมากอน ในกรณีน้ี k จะมีคาเทากับ 5 เพราะb[0] มีคาเปน1 สวน b[1] มีคาเปน 4

ในกรณีท่ีเราไมไดใชคําส่ังกําหนดคาอะเรย เราสามารถกําหนดอะเรยทีหลังไดดวยการกําหนดคาใหกับทีละสมาชิกเปนตัว ๆไป เชน

char c[] = new char[3];c[0] = ‘k’;c[1] = ‘b’;c[2] = ‘x’;

และถาเราไมกําหนดคาใหสมาชิกของอะเรยแตละตัว จาวาเวอรชัวนแมทชีนจะกําหนดคาปกติใหเอง เพราะสมาชิกของอะเรยคือตัวแปรคลาสของอะเรย

ตัวแปรอะเรยทุกตัวเมื่อถูกสรางขึ้น จาวาเวอรชัวนแมทชีนจะแถมตัวแปรคลาสเปนตัวแปรจํานวนเต็มอีกตัวหนึ่งมาใหซึ่งมีคาเทากับจํานวนสมาชิกของอะเรยตัวนั้น (เปลี่ยนคาภายหลังไมได เพราะอะเรยตองมีจํานวนสมาชิกคงที่) ตัวแปรตัวนั้นมีชื่อวา length เชน

int[] x = new x[8];System.out.println(x.length);

ในกรณีน้ีจะไดเลข 8 ออกหนาจอ

ขอนาสังเกตคือ อะเรยเปนวัตถุที่มีแตตัวแปรคลาส ไมมีแมธธอส

ที่ผามมาทั้งหมดอะเรยมีแคหนึ่งมิติ อะเรยสามารถมีไดมากกวาหนึ่งมิติคลาย ๆกับเปนแมทริกซน้ันเอง ตัวอยางของอะเรยสองมิติเปนดังน้ี

double[][] aMatrix = {{1.0, 0.0, 0.0},{0.0, 1.0, 3.0},{2.0, 1.0, 0.0},{0.0, 1.5, 1.5}

};

จํานวนวงเล็บเหลี่ยมที่อยูทาย double บอกจํานวนมิติของอะเรยชื่อ aMatrix ซึ่งม ี4 แถว แถวหนึ่งหนึ่งมีสมาชกิ 3 ตัว หรือม ี3 คอลัมนน้ันเอง บางทีเราเรียกวา aMatrix เปนอะเรยสองมติิแบบ 4 x 3

การประกาศอะเรยหลายมติิ ตําแหนงของเครื่องหมายวงเล็บเหลี่ยมจะอยูตรงไหนก็ไดระหวางชื่อชนิดของตัวแปรสมาชิกกับชื่อของตัวแปร ขอเพียงแตใหนับไดเทากับจํานวนมิติที่เราตองการเชน

char[][] c;char c[][];

Page 84: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 11 อะเรย

84

char[] c[];

เวลามองอะเรยสองมิติ ใหมองวาเปนอะเรยซอนอะเรย เชนในกรณีของ aMatrix ใหมองเปนอะเรยหนึ่งมิติที่มีสมาชกิเปนอะเรย 4 อะเรย สมาชิกแตละตัวก็มีสมาชิกเปนตัวแปร double อยูภายในอีก 3 ตัว ถาเราตองการอางถึงตัวแปร double ท่ีอยูในอะเรยตัวท่ีสอง และเปนสมาชิกตัวที่สามของอะเรย เราใชสัญลักษณ

aMatrix[1][2]

ซ่ึงในกรณีน้ีมีคาเปน 3.0 อยาลืมวาเลขดรรชนีเริ่มจาก 0 มิใช 1 ดังน้ันแถวท่ีสองมีดรรชนีเปน 1 และคอลัมนที่สามมีดรรชนีเปน 2

เราสามารถอางถึงอะเรยท่ีซอนอยูในอะเรยไดดวย เชนถาตองการอางถึงแถวที่สามทั้งแถว เราใชสัญลักษณ

aMatrix [2]

ซ่ึงในกรณีน้ีมีคาเปน {2.0,1.0,0.0} แตในทางตรงกันขามเราไมสามารถอางถึงเปนคอลัมนได เพราะสมาชิกแตละตัวของคอลัมนอยูในอะเรยแถวคนละตัวกัน

ที่จริงแลวอะเรยในแตละแถวไมจําเปนตองมีจํานวนสมาชิกเทากันกไ็ด เชน

short[] [] s = {{3, 2, 2},{2},{1, 0, 2},{1, 2, 1, 1, 1}

};

ในกรณีน้ี s เปนอะเรยสองมติิ มีสมาชกิเปนอะเรยแบบ short ส่ึตัว ซึ่งมีสมาชิกเปนตัวแปร short อยูภายใน 3, 1, 3 และ 5 ตัวตามลําดับ คําส่ังคําส่ังน้ีเปนแคคําส่ังหน่ึงคําส่ัง สังเกตไดจากเครื่องหมาย ; มีแคอันเดียว แตเรานิยมเขียนเปนหลาย ๆบรรทัดโดยแยกแตละแถวของอะเรยไวในแตละบรรทัดเพื่อความสะดวกในการมองเทาน้ัน

ถาเราตองการประกาศและสรางตัวแปร s แตยังไมตองการกําหนดคา รูปแบบของคําส่ังควรเปนดังน้ี

short[][] s = new short[4][];

นั้นคือในกรณีที่จํานวนสมาชิกในแตละแถวไมเทากันเราไมตองระบุจาํนวนคอลัมนเวลาสรางอะเรย แตในทางตรงกันขามรูปแบบคําสั่งตอไปนี้ไมถูกตองตามหลักภาษาจาวา

short[][] s = new short[][3];

เนื่องจากเราไมอาจสรางอะเรยที่ประกอบดวยสมาชิกที่เรายังไมทราบจํานวนแถวได

Page 85: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

12 แมธธอส

คลาส Vehicle มีแมธธอสอยูหนึ่งแมธธอสคือ run()ซึ่งใชนิยามอาการที่รถยนตทุกคันจะตองวิ่งได สวนตัวของแมธธอส run() คือกลุมของคําส่ังท่ีเปนเสมือนการว่ิงของรถยนต ซ่ึงในท่ีน้ีคือคําส่ังใหแสดงผลออกนอกจอวา Iam running เพราะคอมพิวเตอรไมสามารถสรางรถยนตที่วิ่งไดจริง ๆใหเรา

สวนตัวของแมธธอสจะเปนกลุมคําสั่งอะไรก็ไดในภาษาจาวา และสามารถเขียนตอ ๆกันไปไดเร่ือย ๆ เมื่อใดก็ตามที่เราตองการใหจาวาเวอรชัวนแมทชีนทําสิ่งที่เราตองการ เราสามารถทําไดโดยเขียนคําสั่งเหลานั้นไวในแมธธอส จากน้ันก็สรางอินสแตนทของคลาสน้ันข้ึนมาแลวเรียกแมธธอสอินสแตนทออกมาใชงาน ดังตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 12 12 12 12 ---- 1 1 1 1 : TestACar.java: TestACar.java: TestACar.java: TestACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;

void run(){System.out.println(“I am running”);

}

}

public class TestACar {public static void main (String[] args) {

Page 86: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 12 แมธธอส

86

Vehicle myCar = new Vehicle(); // (1)myCar.run(); // (2)

}}

คําส่ังในบรรทัด (1) คือการสรางอินสแตนทของคลาส Vehicle ชื่อ myCar คําส่ังในบรรทัด (2)คือคําส่ังเรียกอินสแตนทแมธธอสของ myCar ที่ชื่อ run()ออกมาทํางาน เราใชชื่อของตัวแปรอางอิงตามดวยจุดนําหนาชื่อแมธธอสในการอางถึงแมธธอสของอินสแตนท ส่ิงท่ีไดก็คือคําวา I am running ที่จะพิมพออกที่หนาจอ

สังเกตวาเรานิยามแมธธอส run() ไวในคลาส Vehicle แตพอจะใชงานมันเราไมสามารถเรียกมันออกมาใชไดโดยตรงเพราะคลาสเปนเพียงนิยามไมมีตัวตน อินสแตนทของคลาสเทานั้นที่มีตัวตนเปนวัตถุจับตองไดในภาษาจาวา เราจึงตองสรางอินสแตนทของคลาส Vehicle ขึ้นมาตัวหนี่งกอน และเรียก run() จากอินสแตนทน้ันทางออม

ภายในนิยามของแมธธอสในคลาสเดียวกันสามารถเรียกใชตัวแปรคลาสและแมธธอสของคลาสนั้นไดดวยตามใจชอบ ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 12 12 12 12 ---- 2 2 2 2 : Vehicle.java: Vehicle.java: Vehicle.java: Vehicle.java

class Vehicle {

int numberOfWheels;boolean hasEngine;

void run(){System.out.println(“I am running”);

}

void checkup() { // (1)if (numberOfWheels < 4)

System.out.println(“I cannot run.”);else

run();}

}

คลาส Vehicle ในตัวอยาง มีแมธธอสตัวใหมชื่อ checkup() ในบรรทัด (1) แมธธอสนี้ทําการตรวจสภาพรถยนตวาวิ่งไดหรือไม โดยการนับจาํนวนลอ ถาจาํนวนลอนอยกวา 4 โปรแกรมจะแสดงขอความวา I cannot run

แตถาจํานวนลอมีมากกวาหรือเทากับ 4 โปรแกรมจะเรียกแมธธอส run()

Page 87: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 12 แมธธอส

87

สังเกตการเรียกใชตัวแปรคลาสและแมธธอสภายในแมธธอส checkup() ใชชื่อของตัวแปรคลาสและแมธธอสไดเลยเพราะอยูในภายในคลาสเดียวกัน ไมมีชื่ออินสแตนทมาเกี่ยวของ

การสงผานตัวแปรเขาไปในแมธธอสและออกจากแมธธอสบางคร้ังเราตองการสงผานตัวแปรเขาไปในแมธธอสหรือออกจากแมธธอส การสงผานตัวแปรเขาไปในแมธธอสทําไดดังตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 12 12 12 12 ---- 3 3 3 3 : DriveACar.java: DriveACar.java: DriveACar.java: DriveACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;

void run(int mile){ // (1)System.out.println(“I am running on the ” + mile + “th mile.” );

// (2)}

}

public class DriveACar {public static void main (String[] args) {

Vehicle myCar = new Vehicle();for (int i = 1;i <= 5; i++) {

myCar.run(i); // (3)}

}}

ในบรรทัด (1) มีการสงผานตัวแปรชื่อ mile ซึ่งเปนตัวแปร int เขาไปในแมธธอส การสงผานตัวแปรทําไดโดยระบุชื่อชนิดของตัวแปร ตามดวยชื่อตัวแปร ในวงเล็บที่อยูหลังชื่อของแมธธอส เราสามารถอางถึงช่ือน้ีท่ีใดก็ไดภายในบลอคปกกาของแมธธอส ในที่นี้ในบรรทัด (2) เรานําตัวแปร mile ไปใชแสดงขอความออกนอกจอวารถของเรากําลังวิ่งอยูที่เลขไมลที่เทาไร

ในบรรทัด (3) เราเรียกแมธธอส run()สิบคร้ัง ดวยการใชคําส่ังวนลูป for ตัวแปร i ในคําส่ัง for ถูกสงผานไปยังแมธธอส run() ดังนั้นตัวแปรชื่อ mile ที่อยูในแมธธอส run() จะมีคาเทากับ i ทุกครั้งที่เรียกแมธธอส

Page 88: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 12 แมธธอส

88

แต i มีคาเพิ่มขึ้นเรื่อย ๆจาก 1 ถึง 5 ทุกคร้ังท่ีวนลูป ผลที่ไดเมื่อรันโปรแกรมนี้ก็คือรถยนต myCar จะวิ่งเปนระยะทางสิบไมล และเมื่อใดที่วิ่งไดครบหนึ่งไมลจะแสดงระยะทางที่วิ่งไดออกมา ดังภาพ

เวลาเรียกแมธธอสที่มีการสงผานตัวแปร เราจะสงผานคาคงตัวหรือตัวแปรเขาไปในแมธธอสก็ได ถาเราสงตัวแปรเขาไปในแมธธอสอยางเชนในกรณีตัวอยาง เราสงตัวแปร i เขาไปในแมธธฮส run() แมธธอส run() จะรับคาคงตัวที่เก็บอยูในตัวแปร i ไปกําหนดใหตัวแปร mile ซึ่งเปนตัวแปรภายในแมธธอส run() คาของตัวแปร i จะไมถูกเปลี่ยนแปลงแตอยางใด ลองพิจารณาโปรแกรมตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 12 12 12 12 ---- 4 4 4 4 : TestMethod.java: TestMethod.java: TestMethod.java: TestMethod.java

class A {

void x(int i){ // (1)i = 10;

}

}

public class TestMethod {public static void main (String[] args) {

A a = new A();a.x(5); // (2)int j = 6;a.x(j); // (3)System.out.println(“j = “ + j);

}}

คลาส A ในโปรแกรมนี้มีแมธธอส x() เปนสมาชิก ในบรรทัด (1) แมธธอส x() รับคาตัวแปร i เขาไปแลวเปลี่ยนคาของตัวแปรเสียใหมเปน 10

ในบรรทัด (2) มีการเรียกใชแมธธอส x() โดยสงคาคงตัว 5 เขาไปในแมธธอส

C:\java> java DriveACarI am running on the 1th mile.I am running on the 2th mile.I am running on the 3th mile.I am running on the 4th mile.I am running on the 5th mile.

Page 89: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 12 แมธธอส

89

ในบรรทัด (3) มีการเรียกใชแมธธอส x() อีกเหมือนกัน แตสงผานตัวแปร j ซึ่งมีคาเปน 6 เขาไปในแมธธอส แมวาคาของตัวแปร j จะถูกสงผานไปยังตัวแปร i ซ่ึงถูกกําหนดคาใหกลายเปน 10 ในแมธธอส แตตัวแปร j จะยังคงมีคาเปน 6 เหมือนเดิมไมเปลี่ยนแปลง ดังจะเห็นไดจากผลการรันในภาพ

ตัวแปรภายในแมธธอสสามารถถูกสงออกมาภายนอกไดดวย ลองพิจารณาตัวอยางโปรแกรมตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 12 12 12 12 ---- 5 5 5 5 : DriveACar.java: DriveACar.java: DriveACar.java: DriveACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;

boolean run(int mile){ // (1)System.out.println(“I am running on the ” + mile + “th mile.” );return (mile < 10); // (2)

}

}

public class DriveACar {public static void main (String[] args) {

Vehicle myCar = new Vehicle();int i = 0;do { // (3)

++i;} while (myCar.run(i)); // (4)

}}

ในบรรทัด (1) เราเปล่ียนคําวา void เปน boolean เมื่อใดก็ตามที่ตองการสงผานตัวแปรออกนอกแมธธอส เราจะเปล่ียนจากคําวา void หนาชื่อแมธธอสเปนชื่อชนิดของตัวแปรที่ตองการสงออก สวนคาของตัวแปรนั้นเรากําหนดไวในบลอคปกกาของแมธธอส โดยใชคําสั่ง return ตัวอยางเชนในบรรทัด (2) ตัวแปรที่สงผานออกมาจะมีคาเทากับคาความจริงของวลี mile < 10

ในบรรทัด (3) เราเปล่ียนคําส่ังการวนลูปจากคําส่ัง for มาเปนคําส่ัง do-while ซ่ึงคราวน้ีเราสรางตัวแปรนับจํานวนคร้ังในการวนลูปข้ึนมาเอง เพราะคําส่ัง do-while ไมสามารถสรางไดเองเหมือนอยางคําส่ัง for ตัวแปร i จะถูกเพิ่มขึ้นทีละหนึ่งจากคาเริ่มตนคือ 0 ทุกคร้ังท่ีวนลูป และ โปรแกรมจะหลุดจากลูปก็ตอเมื่อ คาความจริงในวงเล็บหลังคําส่ัง while เปนเท็จ (ดูในบรรทัด (4)) ซ่ึงในการกรณีน้ีคาความจริงในวงเล็บหลังคําส่ัง while ก็คือ

C:\java> java TestMethodj = 6

Page 90: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 12 แมธธอส

90

myCar.run(i) ซึ่งก็คือคาตัวแปร boolean ที่แมธธอส run() สงผานออกมา คาคานี้จะเปนจริงก็ตอเมื่อ iมึคาไมเกิน 10 ผลที่ไดก็คือรถยนตของเราจะวิ่งแค 25 ไมลเทาน้ัน อีกนัยหน่ึง เรากําจัดการใชงานรถยนตของเราไมใหวิ่งเกิน 10 ไมลดวยการใชการสงผานตัวแปรออกนอกแมธธอส

ผลของการรันโปรแกรมขางตนเปนดังน้ี

การสงผานตัวแปรเขาไปในแมธธอส และการสงผานตัวแปรออกจากแมธธอสสามารถสงตัวแปรอางอิงไดดวย ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 12 12 12 12 ---- 6 6 6 6 : DriveACar.java: DriveACar.java: DriveACar.java: DriveACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;void run(){

System.out.println(“I am running”);}

}

class A { // (1)void x(Vehicle v) {

v.numberOfWheels = 10;}

}

C:\java> java TestMethodI am running on the 1th mile.I am running on the 2th mile.I am running on the 3th mile.I am running on the 4th mile.I am running on the 5th mile.I am running on the 6th mile.I am running on the 7th mile.I am running on the 8th mile.I am running on the 9th mile.I am running on the 10th mile.

Page 91: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 12 แมธธอส

91

public class DriveACar {public static void main (String[] args) {

Vehicle myCar = new Vehicle();A a = new A();a.x(myCar); // (2)System.out.println(myCar.numberOfWheels);

}}

ในโปรแกรมนี้มีคลาสคลาสใหมชื่อคลาส A ในบรรทัด (1) คลาสนี้มีแมธธอสชื่อ x() ซ่ึงสงผานตัวแปรอางอิง vซ่ึงเปนตัวแปรอางอิงของอินสแตนทของคลาส Vehicle สิ่งที่แมธธอส x() ทําก็คือเซตจํานวนลอของ v ใหเทากับ 10

ส่ิงท่ีนาสังเกตก็คือในบรรทัด (2) มีการสงผานตัวแปรอางอิง myCar เขาไปในแมธธอส x() แมวาการสงผานตัวแปรเขาไปในแมธธอสจะเปนแตเพียงการสงผานคา แตอินสแตนทที่ myCar ชี้อยูจะไดรับอิทธิพลของการเซตคาจํานวนลอในแมธธอส x() ดวย ซึ่งตางกับการสงผานตัวแปรทั่วไปซึ่งคาของตัวแปรที่ถูกสงผานจะไมไดรับอิทธิพลใด ๆ

ที่เปนเชนนี้ก็เพราะคาของตัวแปรที่สงผานเขาไปในแมธธอสในกรณีของตัวแปรอางอิงก็คือเลขชี้ตําแหนงในแรม ซ่ึงเมื่อตัวแปร v รับคาของ myCar เขาไป ตัวแปรอางอิง v จึงชี้ไปยังอินสแตนทเดียวกันกับ myCar ในแรม ทําใหเมื่อมีการเปลี่ยนคาของตัวแปร numberOfWheels จึงกระทบ myCar ดวย ผลการรันโปรแกรมจึงเปนดังภาพ

เคยกลาวใหทราบไปแลววา อะเรยในภาษาจาวาเปนวัตถุ ดังน้ันการสงผานอะเรยเขาไปในแมธธอสก็จะกระทบคาเดิมของอะเรยท่ีถูกสงผานดวย เชนเดียวกับในกรณีของอินสแตนท

แมทธธอสซอนแมธธอสเราสามารถเรียกแมธธอสจากขางในตัวของมันเองได เราเรียกโปรแกรมที่มีการเรียกแมธธอสซอนแมธธอสวา โปรแกรมรีเคอรซีฟ ตัวอยางที่นาสนใจไดแกการใชโปรแกรมรีเคอรซีฟในการคํานวนคาแฟกตอเรียล

คาแฟกตอเรียลของจํานวนเต็มตัวหนึ่ง ๆ ใชสัญลักษณแทนดวย x! เชน คาแฟกตอเรียลของ 10 แทนดวย 10!ความหมายของมันคือผลคูณของจํานวนเต็มตั้งแต 1 จนถึงเลขตัวนั้น เชน 10! มีคาเทากับ 1x2x3x4x5x6x7x8x9x10 เปนตน โปรแกรมตัวอยางตอไปนี้เปนโปรแกรมหาคา 12!

C:\java> java DriveACar10

Page 92: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 12 แมธธอส

92

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 12 12 12 12 ---- 7 7 7 7 : Factorial.java: Factorial.java: Factorial.java: Factorial.java

class Number {

long factorialValue(int i){ // (1)if (i == 1) // (2)

return 1;else // (3)

return i*factorialValue(i-1);}

}

public class Factorial {public static void main (String[] args) {

int n = 12;System.out.println( n + “! = “ + newNumber().factorialValue(n)); // (4)

}}

คลาส Number มีแมธธอสชื่อ factorialValue() ซึ่งมีไวสําหรับหาคาแฟกตอเรียลโดยเฉพาะ แมธธอส factorialValue() คืนคา 1 ถาตัวแปรสงผาน i มีคาเปน 1 แตถา i มีคาเปนอ่ืนจะคืนคา i*factorValue(i-1)

ในบรรทัด (4) เราเรียกแมธธอส factorialValue() โดยสงผานคา n = 12 เขาไป factorialValue() พบวาคา i ไมใช 1 ดังนั้นมันควรจะคืนคา i*factorialValue(i-1) หรือ 12*factorialValue(11) แตมันไมรูวา factorialValue(11) มีคาเทาไร มันจึงเรียกตัวเองดวการสงผานคา 11 เขาไป ซ่ีงก็จะเจอปญหาเดิมอีกเพราะ factorialValue(11) จะคืนคา 11*factorialValue(10) มันจะเรียกตัวเองอีกไปเร่ือย ๆจนกวา i จะเปน 1 มันจึงหลุดออกจากการเรียกตัวเองได ซึ่งมันจะหาคายอนกลับมาจนถึง 12 อีกคร้ัง ไดผลเปนดังภาพ

C:\java> java Factorial12! = 479001600

Page 93: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 12 แมธธอส

93

แมธธอสท่ีมีช่ือซํ้ากันตัวแปรคลาสสองตัวหามมีชื่อซ้ํากัน แตในกรณีของแมธธอสสามารถมีชื่อซ้ํากันได เราเรียกวา การโอเวอรโหลดแมธธอส ลองดูตัวอยางตอไปน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 12 12 12 12 ---- 8 8 8 8 : DriveACar.java: DriveACar.java: DriveACar.java: DriveACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;

void run(int mile){ // (1)System.out.println(“I am running on the ” + mile + “th mile.” );

}

void run(float mile){ // (2)System.out.println(“I am running on the ” + mile + “th mile.” );

}

}

public class DriveACar {public static void main (String[] args) {

Vehicle myCar = new Vehicle();myCar.run(10); // (3)myCar.run(10.0F); // (4)

}}

โปรแกรมนี้มีแมธธอสชื่อ run() เหมือนกันสองแมธธอสท่ีบรรทัด (1) และ (2) แตไมมีปญหาเพราะตัวแปรที่สงผานไมเหมือนกัน แมธธอสในบรรทัด (1) สงผานตัวแปร mile ท่ีเปนจาํนวนเต็ม สวนบรรทัด (2) สงผานตัวแปรทศนิยม คอมไพลเลอรจะใชตัวแปรที่สงผานเปนตัวแยกแยะความแตกตาง ผลท่ีไดจะเปนดังภาพ

C:\java> java DriveACarI am running on the 10th mile.I am running on the 10.0th mile.

Page 94: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 12 แมธธอส

94

ในบรรทัด (3) เราเรียกแมธธอส run() โดยสงผานเลขจํานวนเต็ม ดังนั้นจาวาเวอรชัวนแมทชีนจะรันแมธธอสในบรรทัด (1) สวนในบรรทัด (4) เปนการเรียกแมธธอศ run() โดยสงผานเลขทศนิยม จาวาจะรันแมธธอสในบรรทัด (2) สังเกตผลลัพธท่ีออกหนาจอวาจะไมเหมือนกัน

ดังน้ันเราสามารถสรางแมธธอสท่ีมีช่ือซํ้ากันไดตราบใดท่ีการสงผานตัวแปรของแตละแมธธอสไมเหมือนกัน ตัวอยางตอไปน้ีเปนการโอเวอรโหลดแมธธอสรันท่ีเปนไปได

void run() { /* */ }void run(int mile) { /* */ }void run(long mile) { /* */ }void run(int mile, boolean x) { /* */ }int run(int mile, long mile) { /* */ }long run(int mile, long mile, boolean x) { /* */ }

แตหามโอเวอรโหลดแมธธอสที่มีตัวแปรสงผานในวงเล็บเหมือนกัน แตตัวแปรสงกลับตางกัน เพราะคอมไพลเลอรจะแยกความแตกตางไมออกเวลาที่เจอแมธธอสนี้ที่อื่นในโปรแกรม ตัวอยางตอไปนี้เปนแมธธอสสองแมทธธอสที่อยูรวมกันไมได

void run(int mile) { /* */ }int run(int x) { /* */ } // Error

ในกรณีที่ตัวแปรสงผานในแมธธอสหนึ่งเปนจํานวนเต็มแบบ int อีกแมธธอสหนึ่งเปนจํานวนเต็มแบบ long เวลาเรียกใชแมธธอสตองใส L ตอทายตัวสงผานเสมอเพื่อใหทราบวาเปนการสงตัวแปรแบบ long ดวย มิฉะนั้นจาวาเวอรชัวนแมทชีนจะคิดวาตองการใหเรียกแมธธอสที่มีตัวแปรสงผานแบบ int แมวาปกติแลวคาคงตัวจํานวนเต็มที่ไมมี L ตอทายจะใชไดกับตัวแปรแบบ long ก็ตาม ตัวอยางเชน ถาเรามีแมธธอสสองแมธธอสน้ีในคลาสเดียวกัน

boolean run(int mile) { /* */ }boolean run(long mile) { /* */ }

เวลาเรียกใชตองเรียกตางกันดังน้ี

myCar.run(10);myCar.run(10L);

ถาตัวแปรสงผานเปน float กับ double ก็ตองแยกความแตกตางในทํานองเดียวกัน

คําส่ัง thisคงยังจําไดวาตัวแปรคลาส กับ ตัวแปรทองถิ่นในแมธธอสในคลาสเดียวกัน สามารถมีช่ือซํ้ากันได เพราะตัวแปรคลาสเกิดข้ึนเม่ือมีการสรางอินสแตนท แตตัวแปรทองถิ่นเกิดขึ้นเมื่อมีการเรียกใชแมธธอสและตายไปทันทีที่แมธธอสรันเสร็จ จาวาจึงแยกแยะความแตกตางระหวางตัวแปรทั้งสองตัวได

Page 95: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 12 แมธธอส

95

แตบางคร้ังก็เกิดการสับสน คําส่ัง this จึงมีไวแยกแยะความแตกตางในชัดเจนไปเลย ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 12 12 12 12 ---- 9 9 9 9 : TestThis.java: TestThis.java: TestThis.java: TestThis.java

class TestThis {

int a; // (1)float b; // (2)char c; // (3)

void x(int a, float b,char i){ // (4)char c; // (5)this.a = a; // (6)c = i; // (7)this.y(); // (8)y(); // (9)

}

void y() { // (10)System.out.println(“Hello World”);}

}

คลาสน้ีมีตัวแปรคลาสสามตัวไดแก a,b และ c ในบรรทัด (1)(2)(3) แมธธอส x() มีการสงผานตัวแปรที่มีชือ่เหมือนตัวแปรคลาส a และ b ในบรรทัด (4) อีกทั้งยังประกาศตัวแปรภายในแมธธอสชื่อ c ซึ่งซ้ํากับตัวแปรคลาสอีก ในบรรทัด (5)

คําส่ังในบรรทัด (6) ใชคําสั่ง this ตามดวยจุดนําหนา a เปนการชี้เฉพาะเจาะจงลงไปวาหมายถึงตัวแปรคลาส a ที่ประกาศไวในบรรทัด (1) คําส่ังน้ีเปนการกําหนดคาตัวแปรคลาส a ใหมีคาเทากับตัวแปรสงผาน a ซึ่งอยูหลังเครื่องหมายเทากับ ตัวแปรสงผานไมมีคําวา this นําหนา

คําส่ังในบรรทัด (7) เปนการอางถึงตัวแปร c ที่ประกาศไวในบรรทัด (5) เพราะไมมี this นําหนา สรุปก็คือ ถามีการใชชื่อซ้ํากัน การใชชื่อตัวแปรเฉย ๆ จะถือวาเปนตัวแปรภายในแมธธอส ถาตองการอางถึงตัวแปรคลาสตองระบุ this ดวยเสมอ แตถาไมมีการใชชื่อซ้ํากัน ไมตองระบุ this ก็ไดเหมือนกันท่ีเราเคยทํามาในอดีต

คําส่ัง this ใชระบุเฉพาะเจาะจงไดดวยวาหมายถึงแมธธอสในคลาสเดียวกันดังที่ใชในบรรทัด (8) แตเนื่องจากไมมีความสับสนในกรณีของแมธธอสอยูแลว (เพราะไมมีแมธธอสทองถิ่น) การระบุ this จึงไมจําเปนสําหรับการเรียกแมธธอส บรรทัด (8) กับ บรรทัด (9) จึงมึความหมายเหมือนกัน

Page 96: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 12 แมธธอส

96

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

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 12 12 12 12 ---- 10 10 10 10 : TestMethod.java: TestMethod.java: TestMethod.java: TestMethod.java

class Arithmetic {static int triplePower(int i) {

return i*i*i;}

}

public class TestMethod {public static void main (String[] args) {

System.out.println( “10 raised to the power of three is “ +Arithmetic.triplePower(10) +”.”);

System.out.println( “20 raised to the power of three is “ +Arithmetic.triplePower(20) +”.”);

System.out.println( “30 raised to the power of three is “ +Arithmetic.triplePower(30) +”.”);

}}

ผลการรันโปรแกรมขางตนเปนดังน้ี

คลาส Arithmetic มีแมธธอสสแตรติคหนึ่งตัวชื่อ triplePower() ซึ่งคืนคายกกําลังสามของตัวแปรที่สงเขามา แมธธอสนี้ถูกนําไปใชหาคายกกําลังสามของ 10 20 และ 30 ในแมธธอส main()

เราสามารถกําหนดใหแมธธอสในคลาสเปน แมธธอสสแตรติก ไดดวยการใชคําสั่ง static นําหนา เมือ่เวลาจะเรียกใชแมธธอสสแตรติกเราเรียกใชไดเลยโดยเรียกชื่อคลาสตามดวยจุดตามดวยชือ่แมธธอสโดย ไมตองมีการสรางอินสแตนทกอน

C:\java> java TestMethod10 raised to the power of three is 1000.20 raised to the power of three is 8000.30 raised to the power of three is 27000.

Page 97: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 12 แมธธอส

97

นี่เปนเหตุผลที่ทําไมจึงมีคําวา static นําหนาแมธธอส main() เพราะทําใหเราไมตองสรางอินสแตนทของคลาสหลักของโปรแกรมของเรา เราเร่ิมรันโปรแกรมของเราดวยการรันแมธธอส main() ไดเลย เพราะมนัเปนแมธธอสสแตรติก

ภายในตัวแมธธอสสแตรติก หามมีการอางถึงตัวแปรคลาสหรือแมธธอสที่ไมสแตรติกเปนอันขาด เพราะแมธธอสสแตรติคทํางานไดโดยที่ไมตองมีการสรางอินสแตนท แตตัวแปรคลาสและแมธธอสที่ไมสแตรติคจะเกิดขึ้นหลังการสรางอินแสตนทแลวเทาน้ัน

ถาจําเปนตองมีการอางถึงตัวแปรคลาสหรือแมธธอสที่ไมสแตรติกจริง ๆ ภายในแมธธอสสแตรติก สามารถทําไดโดยการสรางอินสแตนทข้ึนช่ัวคราว ดังตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 12 12 12 12 ---- 11 11 11 11 : A.java: A.java: A.java: A.java

class A {int x;static int y;void m() { };static void n() { };static void o() {

int j = y;n();int i = new A().x;new A().m();

}}

ในโปรแกรมน้ีคลาส A มีตัวแปรคลาสสองตัวคือ x และ y แต y เปนตัวแปรสแตรติก มีแมธธอสสามแมธธอสคือ m() n() และ o() โดยที่ n() และ o() สแตรติค

แมธธอส o() เรียกใชงานตัวแปร y และแมธธอส n() ไดเลยเพราะเปนสแตรติกเหมือนกับตน สวน x และ m() ตองเรียกผานการสรางอินสแตนทชั่วคราวขึ้นมา

นอกจากนี้ยังหามใชคําสั่ง this ในแมธธอสสแตรติกดวย เพราะคําวา this แทนชื่อของอินสแตนท แตแมธธอสแตรติกทํางานโดยไมมีอินสแตนท

Page 98: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม
Page 99: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

13 คอนสตรัคเตอร

คงจําไดวาถาไมมีการกําหนดคาเริ่มตนของตัวแปรคลาสไว เวลาสรางอินสแตนท จาวาเวอรชัวนแมทชีน จะกําหนดคาปกติให การกําหนดคาเร่ิมตนทําไดดวยการกําหนดเขาไปเลยตอนนิยามคลาส ดังตัวอยางในโปรแกรม 10 –1

จาวามีแมธธอสพิเศษชนิดหนึ่งชื่อวา คอนสตรัคเตอร ซึ่งเปนแมธธอสที่มีไวสําหรับการกําหนดคาเริ่มตนใหกับตัวแปรอินสแตนทโดยเฉพาะ คอนสตรัคเตอรเปนทางเลือกอีกทางหน่ึงของการกําหนดคาใหตัวแปรคลาส ลองพจิารณาการกําหนดคาเริ่มตนใหตัวแปรคลาสดวยการใชคอนสตรัคเตอรดังตัวอยางขางลางนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 13 13 13 13 ---- 1 1 1 1 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;

Vehicle() { // (1)numberOfWheels = 6;hasEngine = true;

}

void run(){System.out.println(“I am running”);

}

Page 100: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 13 คอนสตรัคเตอร

100

}

public class BuildACar {public static void main (String[] args) {

Vehicle myCar = new Vehicle();System.out.println(“My car has “ + myCar.numberOfWheels + “

wheels.”);System.out.println(“That my car has an engine is “ +

myCar.hasEngine + “.”);}

}

แมธธอสคอนสตรัคเตอรคือแมธธอสในบรรทัด (1)แมธธอสคอนสตรัคเตอรตองมีชือ่เหมือนชือ่คลาสเสมอ แตตามดวย () เพื่อใหรูวาเปนแมธธอส และตองไมมีคําวา void หรือชื่อชนิดของตัวแปรใด ๆนําหนาช่ือคอนสตรัคเตอร

ภายในบลอคปกกาของคอนสตรัสเตอรเราใสคําส่ังกําหนดคาของตัวแปรอนิสแตนทลงไป เมื่อไรก็ตามที่มีการสรางอินสแตนทใหมของคลาส Vehicle ดวยคําส่ัง

Vehicle myCar = new Vehicle();

คําสั่งกําหนดคาตัวแปรอินสแตนทที่อยูในคอนสตรัคเตอรจะทํางานทันที

อันท่ีจริงคอนสตรัคเตอรก็เหมือนกับแมธธอสท่ัวไป คําส่ังท่ีอยูในบลอคปกกาไมจําเปนตองเปนคําส่ังกําหนดคาตัวแปรคลาสเสมอไป จะเปนคําส่ังอยางอ่ืนก็ได คําสั่งเหลานี้จะทํางานทุกครั้งที่มีการสรางอินสแตนทใหมใหคลาส ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 13 13 13 13 ---- 2 2 2 2 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;

Vehicle() {numberOfWheels = 6;hasEngine = true;System.out.println(“A car has been built.”); //(1)

}

void run(){System.out.println(“I am running”);

}

}

Page 101: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 13 คอนสตรัคเตอร

101

public class BuildACar {public static void main (String[] args) {

Vehicle myCar = new Vehicle();System.out.println(“My car has “ + myCar.numberOfWheels + “

wheels.”);System.out.println(“That my car has an engine is “ +

myCar.hasEngine + “.”);}

}

ในบรรทัด (1) เราเติมคําสั่งใหโปรแกรมแสดงผลออกนอกจอวา A car has been built ดังน้ันคําส่ังน้ีจะถูกใชงานเมือ่มีการสรางอินสแตนท myCar ขึ้น ซ่ึงเกิดข้ึนกอนการแสดงจํานวนลอ ดังภาพขางลางนี้

คอนสตรัคเตอรเปนแมธธอส ดังน้ันคอนสตรัคเตอรสามารถสงผานตัวแปรไดดวย เชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 13 13 13 13 ---- 4 4 4 4 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;

Vehicle() {numberOfWheels = 6;hasEngine = true;System.out.println(“A car has been built.”);

}

Vehicle(int number, boolean engine) { // (1)numberOfWheels = number;hasEngine = engine;System.out. println(“A car has been built.”);

}

void run(){System.out.println(“I am running”);

C:\java> java BuildACarA car has been built.My car has 6 wheels.That my car has an engine is true.

Page 102: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 13 คอนสตรัคเตอร

102

}

}

public class BuildACar {public static void main (String[] args) {

Vehicle myCar = new Vehicle(4,true); //(2)System.out.println(“My car has “ + myCar.numberOfWheels + “

wheels.”);System.out.println(“That my car has an engine is “ +

myCar.hasEngine + “.”);}

}

ในตัวอยางนี้เราเพิ่มคอนสตรัคเตอรที่มีการสงผานตัวแปรในบรรทัด (1) ซ่ึงเปนการโอเวอรโหลดคอนสตรัสเตอรท่ีมีอยูเดิม

ในบรรทัด (2) เราสรางอินสแตนทโดยใชคอนสตรัคเตอรตัวใหม ซึ่งมีการสงผานตัวแปรดวย ผลที่ไดก็คือตัวแปรอินสแตนททั้งสองจะมีคาเหมือนกับตัวแปรที่เราสงผาน ดังในภาพ

รถยนตม ี4 ลอแทนที่จะมี 6 ลอ

เราเรียกคอนสตรัคเตอรที่ไมมีการสงผานตัวแปรใด ๆวา คอนสตรัสเตอรปกติ และเรียกคอนสตรัคเตอรท่ีมีการสงผานตัวแปรวา คอนสตรัคเตอรโอเวอรโหลด

คําส่ัง this()ภายในคอนสตรัคเตอรเราสามารถเรียกคอนสตรัคเตอรตัวอ่ืนในคลาสเดียวกันไดดวยการใชคําส่ัง this() ดังตัวอยางตอไปนี้

C:\java> java BuildACarA car has been built.My car has 4 wheels.That my car has an engine is true.

Page 103: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 13 คอนสตรัคเตอร

103

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 13 13 13 13 ---- 5 5 5 5 : TestThis.java: TestThis.java: TestThis.java: TestThis.java

class A {

int a; // (1)

A() {a = 0;System.out.println(“Default Constructor”);

}

A(int i) {this();a = i;System.out.println(“Constructor 1”);

}

A(int i,int j) {this(i+j);System.out.println(“Constructor 2”);

}}

public class TestThis {public static void main(String[] args) {

System.out.println(“Instantiate x”);A x = new A();System.out.println(“variable a is “ + x.a);

System.out.println(“Instantiate y”);A y = new A(5);System.out.println(“variable a is “ + y.a);

System.out.println(“Instantiate z”);A z = new A(5,6);System.out.println(“variable a is “ + z.a);

}}

คลาส A มีสามคอนสตรัคเตอร คอนสตรัสเตอรแรกเปนคอนสตรัสเตอรปกติในบรรทัด (1) กําหนดคาใหตัวแปรคลาส a เปนศูนย คอนสตรัคเตอรท่ีหน่ึงในบรรทัด (2) มีการรับตัวแปร i และ มกีารเรียกคอนสตรัคเตอรปกติดวยคําส่ัง this() กอนท่ีจะเปล่ียนคาต้ังตนของ a ใหเทากับตัวแปร i สวนคอนสตรัคเตอรตัวสุดทายคือคอนสตรัคเตอรท่ีสองในบรรทัด (3) มีการเรียกคอนสตรัสเตอรท่ีหน่ึงดวยคําส่ัง this(i+j) มันจะสงผานคา i+j ไปให a และเน่ืองจากมันเรียกคอนสตรัคเตอรท่ีหน่ึงซ่ึงเรียกคอนสตรัคเตอรปกต ิคอนสตรัคเตอรปกติจึงถูกเรียกไปดวย ลองพิจารณาผลการรันดังภาพ

Page 104: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 13 คอนสตรัคเตอร

104

จําไวเสมอวาคําสั่ง this() ใชไดภายในคอนสตรัคเตอรเทาน้ันและตองเปนคําส่ังแรกสุดเสมอ

C:\java> java TestThisInstatiate xDefault Constructorvariable a is 0Instatiate yDefault ConstructorConstructor 1variable a is 5Instatiate zDefault ConstructorConstructor 1Constructor 2variable a is 11

Page 105: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

14 ตัวแปรสตริง

ถึงตอนนี้เราเขาใจความหมายของคลาสและวัตถุในภาษาจาวาพอสมควรแลว เพื่อใหเห็นภาพของการนําไปใชงานมากขึ้น มาลองรูจักคลาสคลาสหนึ่งที่มีมาใหอยูแลวในภาษาจาวาคือคลาส String

คงยังจําไดวาคาคงตัวในภาษาจาวามีหลายประเภท แตละประเภทจะมีชนิดของตัวแปรที่สอดคลองกับมันอยู เชนคาคงตัวที่เปนตัวเลขจํานวนเต็มแบบ 4 ไบต จะเขากันไดกับตัวแปร int หรือคาคงตัวแบบตัวอักษร จะเขากันไดกับตัวแปรแบบ char แตมีคาคงตัวอยูประเภทหนึ่งที่เรายังไมเคยกลาวถึงตัวแปรที่สอดคลองกับมัน น้ันคือ คาคงตัวแบบขอความ ตัวแปรที่สอดคลองกับคาคงตัวแบบขอความในภาษาจาวาถูกสรางขึ้นจากคลาสท่ีช่ือ String น่ีเอง

การประกาศตัวแปรอางอิงสําหรับคลาส String ทําไดดังตัวอยางตอไปนี้

String string1;

สมมติวาเราตองการจะไดอินสแตนทของคลาส String ที่เก็บคาคงตัวแบบขอความวา “Hello World” เราทําไดดวยการเรียกคอนสตรัคเตอรดังน้ี

string1 = new String(“Hello World”);

คอนสตรัคเตอรของคลาส String มีการสงผานตัวแปรแบบคาคงตัว ซึ่งก็คือคาคงตัวแบบขอความที่เราตองการเก็บน้ันเอง คอนสตรัคเตอรแบบไมมีการสงผานตัวแปรของคลาส String ก็มีเหมือนกันดังน้ี

string1 = new String();

Page 106: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 14 ตัวแปรสตริง

106

ในกรณีน้ีเราจะไดอินสแตนทของคลาส String ที่ไมไดเก็บขอความอะไรเลย มีวิธีกําหนดคาอีกแบบหนึ่งซึ่งเปนที่นิยมใชมากกวาแมจะผิดหลักของการกําหนดคาตัวแปรคลาส คือการจับตัวแปรอางอิงแบบสตริงใหเทากับคาคงตัวแบบขอความเลย ดังน้ี

string1 = “Hello World”;

ตัวแปรอางอิงไมนาจะจับใหเทากับคาคงตัวได แตกรณีน้ีเปนกรณีพิเศษสําหรับตัวแปรสตริงโดยเฉพาะ ลองดูตัวอยางการใชงานตัวแปรสตริงดังตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 14 14 14 14 ---- 1 1 1 1 : TestString.java: TestString.java: TestString.java: TestString.java

public class TestString {public static void main(String[] args) {

String s = “Hello World”; // (1)System.out.println(s);

}}

โปรแกรมน้ีใหผลเหมือนโปรแกรม Hello World ทุกประการ เพียงแตคราวนี้เราใชตัวแปรสตริงแทนการใชคาคงตัวแบบขอความในการแสดงผลออกหนาจอ

ในบรรทัด (1) จะเห็นไดวาเราใชงานคลาส String ราวกับวามันเปนตัวแปรชนิดหนึ่งชื่อสตริงเลย ถึงตอนน้ีคุณอาจสงสัยวาทําไมจาวาจึงไมสรางตัวแปรแบบสตริงในลักษณะเดียวกับตัวแปรแบบอื่น ๆ ทําไมตองสรางเปนคลาสดวย ขอดีอยางหน่ึงของการสรางใหเปนคลาสก็คือเราสามารถสรางแมธธอสขึ้นมาชวยการจัดการตัวแปรแบบสตริง คลาสสตริงมีแมธธอสตอไปนี้พวงมาดวย

int length()

แมธธอส length() คืนคาเปนตัวแปรจํานวนเต็มซึ่งมีคาเทากับความยาวของคาคงตัวแบบขอความที่สตริงเก็บอยู

char charAt(int index)

แมธธอส charAt() รับคาเปนตัวเลขจํานวนเต็มแลวคืนคาเปนตัวแปรแบบอักษรซึ่งเทากับตัวอักษรในลําดับที่เทากับตัวเลขจํานวนเต็มตัวนั้นในขอความ

ลองดูตัวอยางการใชงานแมธธอสทั้งสองดังตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 14 14 14 14 ---- 2 2 2 2 : TestString.java: TestString.java: TestString.java: TestString.java

public class TestString {public static void main(String[] args) {

String s = “Hello World”; // (1)

Page 107: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 14 ตัวแปรสตริง

107

System.out.println(“S is “ + s.length() + “.letter long.”);System.out.println(“the fourth letter is “ + s.charAt(3) + “.”);

}}

ตวอยางนี้เปนการวัดความยาวของขอความดวยการใชแมธธอส length() และหาวาตัวอักษรตัวที่สี่ของขอความคือตัวอะไร สังเกตวาจํานวนเต็มที่สงผานเขาไปในแมธธอส charAt มีคาเปน 3 เนื่องจากอักษรตัวแรกจะเริ่มนับเปนตําแหนงที่ 0 แทนที่จะเปนตําแหนงที่ 1

boolean equals(String s)boolean equalsIgnoreCase(String s)

แมธธอส equals() รับคา สตริงตัวอื่นเขาไปแลวตรวจสอบวามีขอความเหมือนกับสตริงที่เราใชอยูหรือเปลา ในขณะที่แมธธอส equalsIgnoreCase() จะตรวจสอบโดยไมสนใจเรื่อตัวพิมพเล็กตัวพิมพใหญ ลองดูตัวอยางการใชงานดังตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 14 14 14 14 ---- 3 3 3 3 : TestString.java: TestString.java: TestString.java: TestString.java

public class TestString {public static void main(String[] args) {

String s1 = “Hello World”;String s2 = new String(“Hello World”);String s3 = “hello world”;System.out.println(s1.equals(s2)); // (1)System.out.println(s1.equalsIgnoreCase(s3); // (2)System.out.println(s1 == s2); // (3)

}}

วลีในบรรทัด (1) ใหคาเปน true เพราะตัวแปร s1 และ s2 เก็บขอความเหมือนกัน สวนวลีในบรรทัด (3)ก็ใหคาเปน true ดวย เพราะแมจะเขียนตัวพิมพเล็กใหญตางกันเราใชแมธธอส equalsIgnoreCase() ในการเปรียบเทียบ

ในบรรทัด (3) เราเปรียบเทียบดวยการใชเครื่องหมาย == ผลท่ีไดคือ false เพราะเคร่ืองหมาย == จะใหผลเปน true ก็ตอเมื่อตัวแปรอางอิงทางซายชี้อินสแตนทเดียวกันกับตัวแปรอางอิงที่อยูทางขวา แมวา s1 กับ s2จะเก็บขอความเดียวกัน แตเปนคนละอินสแตนทกัน อยูในที่ตางกันในแรม ดังน้ันผลการเปรียบเทียบจะเปน false

Page 108: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 14 ตัวแปรสตริง

108

ตอนนี้คุณอาจสงสัยวาแมธธอส equals ที่จริงแลวสืบทอดมาจากคลาส Object มันควรจะใหผลเหมือนเครื่องหมาย == แตในกรณีนี้กลับมีความแตกตางกันอยู ท่ีเปนเชนน้ีเปนเพราะคลาส String มีการโอเวอรรายดแมธธอส equals() น้ันเอง

int compareTo(String s)

แมธธอส compareTo() เปรียบเทียบลําดับในพจนานุกรมระหวางขอความในสตริง s กับตัวมันเอง ถาขอความเหมือนกันจะคืนคา 0 ออกมา แตถานอยกวา 0 แสดงวาสตริงน้ีมากอนสตริง s ในพจนานุกรม และคืนคามากกวา 0 ถาสตริงน้ีมาหลังสตริง s ในพจนานุกรม ลองดูตัวอยางตอไปน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 14 14 14 14 ---- 4 4 4 4 : TestString.java: TestString.java: TestString.java: TestString.java

public class TestString {public static void main(String[] args) {

String s1 = “abba”;String s2 = “abab”;System.out.println(s1.compareTo(s2));

}}

String toUpperCase()String toLowerCase()

แมธธอส toUpperCase() คืนคาสตริงตัวเดิม แตเปลี่ยนใหเปนตัวพิมพใหญทั้งหมด สวนแมธธอส toLowerCase() คืนคาที่เปนตัวพิมพเล็ก

String concat(String s)

แมธธอส concat คืนคาของสตริงแตตอทายดวยคาของสตริง s หนึ่งอีกนัยหนึ่งก็คือใหผลเหมือนกันเครื่องหมาย + น่ันเอง

String trim()

แมธธอส trim() คือคาเดิมของสตริง โดยที่ถามีชองวางที่ตนขอความหรือทายขอความจะทําการตัดออก

String substring(int startIndex)String substring(int startIndex, int endIndex)

แมธธอส subString() คือคาเดิมของสตริงโดยตัดตัวอักษรที่อยูหนาตัวอักษรตั้งแตตําแหนงที่ startIndexออก แมธธอสนี้มีการโอเวอรโหลดดวย กลาวคือถาคา endIndex ดวยจะคืนคาเฉพาะขอความที่อยูระหวางตําแหนง startIndex ถึง endIndex

ลองดูตัวอยางการใชงานแมธธอสเหลานี้ดู

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 14 14 14 14 ---- 5 5 5 5 : TestString.java: TestString.java: TestString.java: TestString.java

Page 109: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 14 ตัวแปรสตริง

109

public class TestString {public static void main(String[] args) {

String s1 = “ Hello World”;String s2 = “ 2000”;System.out.println(s1.toUpperCase());System.out.println(s1.toLowerCase());System.out.println(s1.concat(“ 2000 ”));System.out.println(s1.concat(“ 2000 “).trim());System.out.println(s1.substring(2,5));

}}

โปรดสังเกตชองวางหนาคาคงตัวแบบขอความในบรรทัด (1) (2)

ผลการรันโปรแกรมขางตนเปนดังน้ี

สังเกตวาแมธธอส substring(2,5) จะรวมตัวอักษรตําแหนง 2 แตกลับตัดตัวอักษรตําแหนง 5 ออก

int indexOf(int ch)int indexOf(int ch, int fromIndex)int indexOf(String s)int indexOf(String s, int fromIndex)

แมธธอส indexOf() คืนคาตําแหนงของตัวอักษร ch ในสตริง และทันทีที่หาเจอเปนครั้งแรกมันจะหยุดหาทันที ถาไมพบมันจะคืนคา –1 เราสามารถกําหนดใหเริ่มหาตั้งแตตําแหนง fromIndex แทนที่จะหาตั้งแตตนไดดวย นอกจากนี้เราอาจใหหาขอความก็ไดดวยการสงคาตัวแปร s

int lastIndexOf(int ch)int lastIndexOf(int ch, int fromIndex)int lastIndexOf(String s)int lastIndexOf(String s, int fromIndex)

แมธธอส indexOf() เริ่มหาจากตนจนจบ แตแมธธอส lastIndexOf() จะหาจากทายมาตน

String replace(char old, char new)

แมธธอส replace() คืนคาเดิมของสตริงโดยเปลี่ยนตัวอักษร old ทุกตัวในขอความเปน new

C:\java> java TestStringHELLO WORLDhello worldHello World 2000

Hello World 2000ell

Page 110: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 14 ตัวแปรสตริง

110

ลองดูตัวอยางการใชงานดังตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 14 14 14 14 ---- 6 6 6 6 : TestString.java: TestString.java: TestString.java: TestString.java

public class TestString {public static void main(String[] args) {

String s1 = “Hello Hello”;System.out.println(s1.indexOf(‘o’));System.out.println(s1.indexOf(“lo”,7));System.out.println(s1.lastIndexOf(‘e’));System.out.println(s1.replace(‘o’,’a’));

}}

ผลการรันโปรแกรมเปนดังน้ี

static String valueOf(int i)static String valueOf(long l)static String valueOf(float f)static String valueOf(double d)static String valueOf(boolean b)static String valueOf(char c)

แมธธอส valueOf() เปลี่ยนคาของตัวแปรในวงเล็บใหเปนตัวแปรสตริง สังเกตวาแมธธอสน้ีเปนแมธธอสสแตรติกดังนั้นสามารถนําไปใชไดโดยไมตองสรางอินสแตนทของคลาส String

static String valueOf(Object obj)

แมธธอส valueOf() สามารถคือคาท่ีเปนช่ือของคลาส obj ไดดวย

static String valueOf(char[] character)

ถาเรามีอะเรยของ char เราสามารถใชแมธธอส valueOf() เปล่ียนใหเปนสตริงได โดยมันจะจับตัวอักษรมาเรียงตอกันตามลําดับในอะเรย

ลองดูตัวอยางการใชงาน

C:\java> java TestString497Hella Hella

Page 111: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 14 ตัวแปรสตริง

111

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 14 14 14 14 ---- 7 7 7 7 : TestString.java: TestString.java: TestString.java: TestString.java

public class TestString {public static void main(String[] args) {

boolean b1 = false;char ch1 = ‘x’;Object o = new Object();char[] ch2 = {‘a’,’b’,’b’,’a’};System.out.println(String.valueOf(5));System.out.println(String.valueOf(5L));System.out.println(String.valueOf(5.0));System.out.println(String.valueOf(b1));System.out.println(String.valueOf(ch1));System.out.println(String.valueOf(o));System.out.println(String.valueOf(ch2));

}}

คลาส StringBufferถาสังเกตดูใหดีจะเห็นวาแมธธอสในคลาส String ทําหนาที่แคสงผานสตริงที่ถูกดัดแปลงออกมาใหเทานั้น ไมไดดัดแปลงตัวสตริงเองแตอยางใด ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 14141414 ---- 8 8 8 8 : TestString.java: TestString.java: TestString.java: TestString.java

public class TestString {public static void main(String[] args) {

String s = “Hello World”;System.out.println(s.substring(1,10)); // (1)

C:\java> java TestString555.0falsexjava.lang.Object@273d3cabba

Page 112: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 14 ตัวแปรสตริง

112

System.out.println(s); // (2)}

}

ในบรรทัด (1) เปนการแสดงคาของสตริง s ที่ตัดหัวตัวหางออกอยางละหนึ่งตัวอักษร ผลท่ีไดคือ ello Worl

แตเมื่อแสดงคาของตัวแปร s ในบรรทัด (2) ใหมจะเห็นวามีคาเปน Hello World อยูเหมือนเดิม

คลาส StringBuffer คลายกับคลาส String เพียงแตเปนตัวแปรสตริงแบบที่มีแกไขคาแบบถาวร คอนสตรัคเตอรของคลาส StringBuffer มีดังน้ี

StringBuffer(String s)

ตัวแปร s คือขอความที่ตองการใหเก็บไวในตัวแปร StringBuffer

StringBuffer()

แบบนี้จะไดขอความวางเปลา แตขนาดของมันจะไมเปน 0 แตเปน 16

StringBuffer(int length)

แบบนี้ไดขอความวางเปลาเหมือนกัน แตกําหนดขนาดไดดวยตัวแปร length

ขอแตกตางที่สําคัญของคลาส StringBuffer กับคลาส String อีกอันหน่ึงก็คือ ขนาดของ StringBuffer ไมจําเปนตองเทากับขนาดของขอความ และสามารถเพ่ิมหรือลดขนาดได เราสามารถตรวจสอบขนาดของ StringBuffer ไดดวยแมธธอส capacity()

int capacity()

แมธธอส capacity()คืนคาขนาดปจจุบันของ StringBuffer

ลองดูตัวอยางตอไปน้ี

โโโโปรแกรม ปรแกรม ปรแกรม ปรแกรม 14 14 14 14 ---- 9 9 9 9 : TestString.java: TestString.java: TestString.java: TestString.java

public class TestString {public static void main(String[] args) {

StringBuffer s1 = new StringBuffer();// (1)System.out.println(s1);System.out.println(s1.length());System.out.println(s1.capacity());StringBuffer s2 = new StringBuffer(“Hello”); // (2)System.out.println(s2);System.out.println(s2.length());System.out.println(s2.capacity());//StringBuffer s3 = “Hello”; // (3) Error

}}

Page 113: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 14 ตัวแปรสตริง

113

ผลการรันเปนดังน้ี

ในบรรทัด (1) เราสรางตัวแปร s1 โดยไมเก็บคาอะไรเลย ผลท่ีไดคือขนาดของขอความเทากับ 0 แตขนาดของตัวมันเองจริง ๆ เทากับ 16 ซึ่งเปนคาปกติของมัน

ในบรรทัด (2) เราสรางตัวแปร s2 โดยใหเก็บขอความ Hello ผลที่ไดคือขนาดขอความจะเปน 5 แตขนาดของตัวมันเองจะเทากับคาปกติบอกดวยความยาวของขอความที่สั่งใหมันเก็บ หรือเทากับ 21

ในบรรทัด (3) เราพยายามสรางตัวแปร s3 โดยใชวิธีเดียวกับเวลาสรางตัวแปรสตริง วิธีนี้ใชไมไดกับตัวแปร StringBuffer

เหตุที่ตัวแปร StringBuffer มีขนาดปกติ 16 และจะเพิ่มขนาดเมื่อเก็บขอความลงไป เปนเพราะถามีการเปล่ียนขอความที่เก็บภายหลัง ขอความใหมอาจมีขนาดไมเทาเดิม จาวาจึงเผื่อที่วางไวอีก 16 ที่วาง เพื่อจะไดไมตองกันที่ในแรมเพิ่มเติมอีกในกรณีที่ขอความใหมมีขนาดใหญกวาเดิมไมเกิน 16 เพราะการกันที่ในแรมเพิ่มเติมภายหลังเปนเรื่องท่ีไมนาสนุก เพราะที่ในแรมที่เพิ่มขึ้นอาจไมอยูติดกับที่เดิมทําใหประสิทธิภาพในการเขาถึงลดลง

ตอไปนี้เปนแมธธอสที่นาสนใจของคลาส StringBuffer จําไววาถามีการเปลี่ยนแปลงขอความในStringBuffer ผานแมธธอส ขอความจะถูกเปลี่ยนแบบถาวร

StringBuffer append(String s)StringBuffer append(char c)StringBuffer append(char[] c, int offset, int len)StringBuffer append(boolean b)StringBuffer append(int i)StringBuffer append(long l)StringBuffer append(float f)StringBuffer append(double d)

แมธธอสเหลานี้จะเพิ่มขอความในวงเล็บเขาไปทายขอความที่มีอยูแลวใน StringBuffer

StringBuffer insert(int offset, String s)StringBuffer insert(int offset, char c)StringBuffer insert(int offset, char[] c)

C:\java> java TestString

016Hello521

Page 114: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 14 ตัวแปรสตริง

114

StringBuffer insert(int offset, boolean b)StringBuffer insert(int offset, int i)StringBuffer insert(int offset, long l)StringBuffer insert(int offset, float f)StringBuffer insert(int offset, double d)

แมธธอสเหลานั้นเหมือนกับ append แตแทนที่จะตอทายกลับแทรกเขาไปในตําแหนงที่เทากับ offset

StringBuffer deleteCharAt(int index)StringBuffer delete(int start, int end)

แมธธอส deleteCharAt() ลบตัวอักษรในตําแหนง index ออก สวนแมธธอส delete() ลบออกตั้งแตตําแหนง start จนถึง end แตไมรวม end

StringBuffer reverse()

แมธธอส reverse() กลับตัวอักษรที่มีอยูเดิมใหมจากหลังมาหนา

ลองดูตัวอยางการใชงานดังตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 14 14 14 14 ---- 10 10 10 10 : TestString.java: TestString.java: TestString.java: TestString.java

public class TestString {public static void main(String[] args) {

StringBuffer s1 = new StringBuffer(“banana split”);// (1)s1.delete(4,12); // “bana”s1.append(42); // “bana42”s1.insert(4,”na”); // “banana42”s1.setCharAt(0,’s’); //sanana42”s1.reverse(); “24ananas”

}}

char charAt(int index)char setCharAt(int index, char ch)

แมธธอส charAt() สงคาตัวอักษรในตําแหนง index กลับ สวนแมธธอส setCharAt() เปล่ียนคาตัวอักษรในตําแหนง index ดวย ch

ถาเราตองการสงคาของ StringBuffer ใหตัวแปรสตริงเราทําไดโดยใชแมธธอส toString()

String toString()

แมธธอส toString() สงคาของขอความออกมาในรูปตัวแปรสตริง ตัวอยางการใชงานก็เชนString str = strBuff.toString();

Page 115: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 14 ตัวแปรสตริง

115

สตริง argsตอนนี้คุณคงพอจะรูแลววาแมธธอส main() มีการสงผานอะเรยช่ือ args เปนอะเรยของตัวแปรสตริง ตัวแปร args มีไวรับคาพารามิเตอรอะไรก็ตามที่อยูหลังชื่อโปรแกรมในคําสั่ง java ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 14 14 14 14 ---- 11 11 11 11 : TestString.java: TestString.java: TestString.java: TestString.java

public class TestString {public static void main(String[] args) {

System.out.println(args[0]);System.out.println(args[1]);System.out.println(args[2]);

}}

ลองรันโปรแกรมขางตนโดยมีการสงผานขอความเขาไปในตัวแปร args ดังน้ี

น้ันคืออะเรย args จะเก็บขอความหลังชื่อคลาสในคําสั่ง java ซึ่งขอความที่ตามมานี้จะมีกี่ตัวก็ได เราอาจนําขอความเหลาน้ีไปใชในโปรแกรมของเราเพ่ือประโยชนใด ๆก็ได

C:\java> java TestString Hello World 2000HelloWorld2000

Page 116: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม
Page 117: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

15 คลาสสําหรับตัวแปรพ้ืนฐาน

ในภาษาจาวาตัวแปรพื้นฐานอื่น ๆ นอกจากตัวแปรสตริงไมไดเปนวัตถุ แตจาวาก็จะมีคลาสที่ทํางานไดเหมือนกับมันอยูดวย ชื่อของคลาสเหลานี้จะเหมือนกับชื่อชนิดของตัวแปรแตขึ้นตนดวยอักษรตัวใหญเพราะเปนชื่อคลาส การใชงานของคลาสเหลาน้ีก็คลาย ๆกับคลาส String

คอนสตรัคเตอรของสําหรับคลาสเหลาน้ี จะรับคาของตัวแปรนั้น ๆ ตัวอยางเชน

Integer intObj = new Integer(2000);Double douObj = new Double(3.56);Character charObj = new Character(‘a’);Boolean booObj = new Boolean(false);

นอกจากน้ียังมีคอนสตรัคเตอรโอเวอรโหลดอีกอันหน่ึงซ่ึงรับคาของตัวแปรในรูปของขอความไดดวย เชน

Integer intObj = new Integer(“2000”);Double douObj = new Double(“3.56”);Character charObj = new Character(“a”);Boolean booObj = new Boolean(“false”);

สิ่งที่ไดจากการใชงานตัวแปรพื้นฐานในรูปของคลาสก็คือแมธธอสชวยเหลือที่มีมาให ที่นาสนใจมีดังตอไปนี้

ถาตองการสงผานคาจากตัวแปรเหลานี้ไปเปนตัวแปรพื้นฐานใชแมธธอส typeValue() โดยแทนคําวา typeดวยชื่อของตัวแปร เชน

Page 118: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 15 คลาสสําหรับตวัแปรพ้ืนฐาน

118

int i = intObj.intValue();char c = charObj.charValue();

ถาตองการสงผานคาจากตัวแปรเหลานี้ไปเปนตัวแปรสตริงใชแมธธอส toString() เชน

String intString = intObj.toString();String charString = charObj.toString();

และถาตองการสงผานคาตัวแปรสตริงไปเปนตัวแปรพ้ืนฐาน คลาสของตัวแปรพื้นฐานเหลานี้จะมีแมธธอสสแตรติกที่ทําหนาที่เหลานี้ใหคือแมธธอส parseType() เชน

double d = Double.parseDouble(“3.14”);boolean b = Boolean.parseBoolean(“false”);

แมธธอสเหลานี้อางถึงไดทันที ไมจําเปนตองมีการสรางอินสแตนทของ Double หรือ Boolean กอน เน่ืองจากแมธธอสขางตนเหลานี้เปนแมธธอสสแตรติก

คลาสของตัวแปรพื้นฐานเหลานี้มีตัวแปรถาวรที่เปนตัวแปรสแตรติก ท่ีแทนคาสูงสุดและตํ่าสุดท่ีเปนไปไดของแตละตัวแปรพ้ืนฐานดวยดังน้ี

Integer.MIX_VALUEInteger.MAX_VALUEDouble.MIX_VALUEDouble.MAX_VALUEByte.MIX_VALUEByte.MAX_VALUELong.MIX_VALUELong.MAX_VALUEShort.MIX_VALUEShort.MAX_VALUEFloat.MIX_VALUEFloat.MAX_VALUECharacter.MIN_VALUECharacter.MAX_VALUEBoolean.TRUEBoolean.FALSE

สําหรับ Boolean ไมมีคาสูงสุดตํ่าสุด จึงมีแตคาที่เปนไปไดสองคาคือ true และ false แทน ลองดูตัวอยางการใชงาน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 15 15 15 15 ---- 1 1 1 1 : TestWrapper.java: TestWrapper.java: TestWrapper.java: TestWrapper.java

public class TestWrapper {public static void main(String[] args) {

double d = Double.MAX_VALUE;System.out.println(d);

}

Page 119: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 15 คลาสสําหรับตวัแปรพ้ืนฐาน

119

}

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

ถาตองการเปรียบเทียบคาระหวางสองอินสแตนทใชแมธธอส equals() เชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 15 15 15 15 ---- 2 2 2 2 : TestWrapper.java: TestWrapper.java: TestWrapper.java: TestWrapper.java

public class TestWrapper {public static void main(String[] args) {

Character c1 = new Character(‘a’);Character c2 = new Character(‘a’);System.out.println(c1.equals(c2));

}}

คลาส Character มีแมธธอสสําหรับตรวจสอบคาที่นาสนใจอีกดงนี้คือ

static boolean isLowerCase(char ch)static boolean isUpperCase(char ch)static boolean isTitleCase(char ch)static boolean isDigit(char ch)static boolean isLetter(char ch)static boolean toUpperCase(char ch) static boolean toLowerCase(char ch) static boolean toTitleCase(char ch)

ตัวอยางเชน ถาตองการตรวจสอบวาตัวอักษรเปนตัวพิมพเล็กหรือไม ถาใชใหเปลี่ยนเปนตัวพิมพใหญ ก็ทําไดดังน้ีchar c = ‘a’;

C:\java> java TestWrapper1.7976931348623157E308

Page 120: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 15 คลาสสําหรับตวัแปรพ้ืนฐาน

120

if (Character.isLowerCase(c)) c = Character.toUpperCase(c);

Page 121: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

16 คลาส Math

คลาส Math เปนคลาสที่จาวามีมาใหสําหรับการจัดการทางคณิตศาสตร

คลาสนี้มีคาคงตัวที่นาสนใจอยูสองตัวคือ Math.EMath.PI

ซึ่งเทากับคาล็อกธรรมชาติ และคาพายน่ันเอง

แมธธอสท่ีนาสนใจสําหรับคลาสน้ีไดแก

static int abs(int i)static long abs(long l)static float abs(float f)static double abs(double d)

ซ่ึงคืนคาสัมบูรณของตัวเลขในวงเล็บ

static double ceil(double d)

คืนคาเทากับจํานวนเต็มที่ใกลเคียงคาในวงเล็บที่สุด แตมากกวาคาในวงเล็บ หรือก็คือการปดเศษข้ึนน่ันเอง

static double floor(double d)

คือการปดลง

static int round(float f)static long round(double d)

Page 122: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 16 คลาส Math

122

คือการปดเศษตามหลักมาตรฐาน กลาวคือถาตํ่ากวา .5 ก็ปดลง นอกน้ันปดข้ึน

static int min(int a, int b)static long min(long a, long b)static float min(float a, float b)static double min(double a, double b)

คืนคาที่นอยกวาระหวาง a หรือ b

static int max(int a, int b)static long max(long a, long b)static float max(float a, float b)static double max(double a, double b)

คืนคาที่นอยกวาระหวาง a หรือ b

static double pow(double d1, double d2)

คืนคา d1 ยกกําลัง d2

static double exp(double d)

คืนคา e ยกกําลัง d

static double log(double d)

คืนคาล็อกธรรมชาติของ d

static sqrt(double d)

คืนคายกกําลังสองของ d

static double sin(double d)static double cos(double d)static double tan(double d)

คืนคาตรีโกณมิติของ d

static double random()

คืนคาตัวเลขทศนิยมที่สุมมาจาก 0.0 ถึง 1.0 บนการกระจายปกติ

ลองดูตวอยางการใชงานแมธธอสสแตรติกเหลานี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 16 16 16 16 ---- 1 1 1 1 : TestMath.java: TestMath.java: TestMath.java: TestMath.java

public class TestMath {public static void main(String[] args) {

double d = -5.456;System.out.println(d);d = Math.abs(d);System.out.println(d);d = Math.ceil(d);System.out.println(d);

Page 123: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 16 คลาส Math

123

double e = Math.random();System.out.println(e);e = Math.random();System.out.println(e);

}}

C:\java> java TestMath-5.4565.4566.00.96527050700228610.34808306194739037

Page 124: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม
Page 125: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

17 การสืบทอด

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

ในบทท่ีแลวเราสรางไดคลาส Vehicle ขึ้นมา คลาส Vehicle นิยามสิ่งที่ใชตัดสินวาวัตถุที่จัดวาเปนรถยนตตองมีคุณสมบัติและพฤติกรรมอะไรบาง คราวนี้ถาเราตองการสรางนิยามที่มีความเฉพาะเจาะจงมากขึ้น เชนนิยามของรถบรรทุก นิยมของรถเกง เราอาจสรางคลาสใหมชื่อ Truck กับ PrivateCar ซึ่งนิยามคุณสมบัติและพฤติกรรมที่มีเฉพาะแตในรถบรรทุกและรถเกง

แทนที่เราจะสรางคลาสทั้งสองขึ้นมาใหมตั้งแตตน เราอาจใชคลาส Vehicle เปนตนแบบ เพราะท้ังรถบรรทุก และรถเกงยอมตองมีลอ มีเคร่ือง และวิ่งได จากนั้นคอยเติมคุณสมบัติและพฤติกรรมอื่น ๆที่มีเฉพาะในรถบรรทุก หรือรถเกงเขาไป เราทําเชนน้ีไดโดยการสรางสับคลาสของซูปเปอรคลาส Vehicle สองตัวชื่อ Truck และ PrivateCar ดังตัวอยางตอไปนี้

Vehicle

Truck PrivateCar

Page 126: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

126

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 17 17 17 17 ---- 1 1 1 1 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;

void run(){System.out.println(“I am running.”);

}

}

class Truck extends Vehicle { // (1)

float maximumLoad; // (2)

void load(float weight) { // (3)if (weight <= maximumLoad)

System.out.println(“I am carrying a “ + weight + “-pound load.”);}}

class PrivateCar extends Vehicle { // (4)

int numberOfPassengers; // (5)

void playCD() { // (6)System.out.println(“CD is playing.”);

}}

public class BuildACar {public static void main(String[] args) {

Truck isuzu = new Truck();PrivateCar toyota = new PrivateCar();isuzu.numberOfWheels = 6;toyota.numberOfWheels = 4;isuzu.maximumLoad = 1500.00F;toyota.numberOfPassengers = 5;isuzu.load(700.0F);isuzu.run();toyota.playCD();toyota.run();

}}

Page 127: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

127

ในบรรทัด (1),(4) เราประกาศคลาสใหมชื่อ Truck และ PrivateCar ซ่ึงเปนสับคลาสของคลาส Vehicle ที่มีอยูแลว โดยเราใชคําสั่ง extends ตามดวยช่ือซูปเปอรคลาส สิ่งที่ไดมาโดยอัตโนมัติคือทั้งคลาส Truck และ PrivateCar จะมีตัวแปรชื่อ noOfWheels, hasEngine และมีแมธธอสชื่อ run() พวงมาดวยทันที

จากน้ันเราสามารถสรางตัวแปรคลาสและแมธธอสเพ่ิมเติมได เพื่อใชเปนสิ่งที่บอกลักษณะที่มีเฉพาะแตในรถบรรทุกหรือรถเกง ในบรรทัด(2)เราสรางตัวแปร maximumLoad ใหคลาส Truck เพ่ือใชในระบุนํ้าหนักบรรทุกสูงสุดของรถบรรทุก และสรางแมธธอส load() ในบรรทัด (3) เพราะส่ิงท่ีรถบรรทุกตองทําไดคือการบรรทุกของ

ในบรรทัด (5) เราสรางตัวแปร numberOfPassengers ใหคลาส PrivateCar เพื่อใชระบุจํานวนผูนั่ง รถเกงควรมีเคร่ืองเลนซีดีดวย เพื่อใหเกิดความแตกตางกับรถบรรทุก ดังนั้นเราจึงสรางแมธธอส playCD() ในบรรทัด (6)

คําส่ังในแมธธอส main() เปนการสรางอินสแตนทใหกับคลาส Truck และ PrivateCar อยางละหน่ึงอินสแตนท สังเกตวาอินสแตนททั้งสองมีตัวแปร numberOfWheels และแมธธอส run()ทั้งที่ไมไดสรางไวในคลาส ท่ีเปนเชนน้ีเพราะคลาสท้ังสองสืบทอดคุณลักษณะของคลาส Vehicle ผลการรันโปรแกรมขางตนจะเปนดังภาพ

เราสามารถสรางสับคลาสของสับคลาสไดดวย ดังน้ันคุณลักษณะของคลาสสามารถสืบทอดตอกันไปไดเร่ือย ๆ ไมมีที่ส้ินสุด คลาสคลาสหน่ึงมีไดหลายสับคลาสเชนในกรณีของคลาส Vehicle มีสองสับคลาสคือ Truck และ PrivateCar แตคลาสคลาสหน่ึงในภาษาจาวามีไดแคซูปเปอรคลาสเดียว กลาวคือเม่ือ Truck สืบทอดคุณลักษณะจากซูปเปอรคลาส Vehicle แลว คลาส Truck ไมสามารถสืบทอดคุณลักษณะจากคลาสอ่ืนไดอีก คําส่ัง extends จึงตามดวยช่ือซูปเปอรคลาสไดแคซูปเปอรคลาสเดียวเทาน้ัน

คลาสนามธรรมคลาสคือนิยามของวัตถุ เราสรางวัตถุข้ึนจากการสรางอินสแตนทของคลาส แตในภาษาจาวาเราสามารถสรางคลาสท่ีไมอนุญาตใหนําไปสรางอินสแตนทไดดวย เราเรียกคลาสเหลาน้ันวา คลาสนามธรรม ลองพิจารณาตัวอยางตอไปนี้

C:\java> java BuildACarI am carrying a 700.0-pound load.I am running.CD is playing.I am running.

Page 128: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

128

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 17 17 17 17 ---- 2 2 2 2 : TestAbstract.jav: TestAbstract.jav: TestAbstract.jav: TestAbstract.javaaaa

abstract class A { // (1)

}

public class TestAbstract {public static void main (String[] args) {

// A a = new A(); // Error (2)

}}

ในบรรทัด (1) เปนการนิยามคลาส A ซึ่งกําหนดใหเปนคลาสนามธรรมดวยการใชคําสั่ง abstract นําหนาคําส่ัง class ผลท่ีไดก็คือ หามสรางอินสแตนทของคลาส A ดังในบรรทัด (2)

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

ท่ีผานมาเราสรางคลาส Vehicle ขึ้นมาโดยประกาศตัวแปรคลาส numberOfWheels hasEngine และแมธธอส run() ซึ่งเปนลักษณะรวมของรถยนตทุกชนิด จากน้ันเราก็สรางคลาส Truck และ PrivateCar ใหสืบทอดคลาส Vehicle ซึ่งจะไดตัวแปรคลาสและแมธธอสมาโดยอัติโนมัติ จากนั้นก็นิยามตัวแปรและแมธธอสือื่นที่เปนลักษณะเฉพาะของรถแตละชนิดในตัวของคลาสน้ัน ๆเองทีหลัง ในกรณีถานักเขียนโปรแกรมไมตองการใหใครสรางอินสแตนท Vehicle นักเขียนโปรแกรมสามารถทําไดโดยกําหนดใหคลาส Vehicle เปนคลาสนามธรรม

คลาสถาวรคลาสถาวร คือ คลาสที่ไมอนุญาตใหนําไปใชสืบทอด

เราสามารถกําหนดใหคลาสของเราเปนคลาสถาวรไดดวยการใชคําส่ัง final นําหนาคําส่ัง class ดังตัวอยางตอไปน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 17 17 17 17 ---- 3 3 3 3 : TestFinal.java: TestFinal.java: TestFinal.java: TestFinal.java

Page 129: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

129

final class A { // (1)}/*class B extends A { // (2)

}*/public class TestAbstract {

public static void main (String[] args) {A a = new A(); // (3)

}}

คลาส A ในบรรทัด (1) ถูกกําหนดใหเปน คลาสถาวร การสรางคลาส B ในบรรทัด (2) จึงทําไมไดเพราะคลาส B สืบทอดคลาส A

ประโยชนของคําสั่งถาวรคือ การปองกันไมใหนักเขียนโปรแกรมคนอ่ืนเอาคลาสของเราไปสืบทอดโดยไมบอกกลาว เพราะอาจทําใหเกิดการสับสน

ตอนท่ีเรากลาวถึงคลาสนามธรรมจะเห็นไดวา คลาสนามธรรม มักใชเปนตนแบบสําหรับคลาสอื่น ดังนั้นจึงไมมีเหตุผลท่ีจะกําหนดใหคลาสนามธรรมเปนคลาสถาวร เพราะคลาสนามธรรมจะมีประโยชนก็ตอเมือ่เรานํามันไปสืบทอด ดวยเหตุน้ี คําส่ัง final และคําส่ัง abstract จะใชนําหนาคลาสเดียวกันไมได

คลาส String เปนคลาสถาวร คุณไมสามารถสรางคลาสท่ีสืบทอดคลาส String ได

การโอเวอรรายดแมธธอส

เราสามารถสรางแมธธอสที่มีชื่อเหมือนแมธธอสของซูปเปอรคลาสในสับคลาสไดดวย เราเรียกวา การโอเวอรรายด แมธธอสใหมจะแทนที่แมธธอสเกา ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 17 17 17 17 ---- 4 4 4 4 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;

void run(){ // (1)System.out.println(“I am running”);

}

Page 130: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

130

}

class PrivateCar extends Vehicle {

int numberOfPassengers;

void playCD() {System.out.println(“CD is playing.”);

}

void run() { // (2)System.out.println(“I am a running car.”);

}}

public class BuildACar {public static void main(String[] args) {

PrivateCar toyota = new PrivateCar();toyota.run(); // (3)

}}

ในบรรทัด (2) เราสรางแมธธอส run() ซึ่งมีชื่อซ้ํากับแมธธอส run() ในบรรทัด (1) ถาลองรันโปรแกรมน้ีดูจะพบวาจาวาเวอรชัวนแมทชีนจะเลือกรันแมธธอส run() ตัวใหม ดังในภาพ

ขอความที่ปรากฎคือคําวา I am a running car แทนที่จะเปน I am running เหมือนเคย

การโอเวอรรายดแมธธอส นอกจากจะตองใชชื่อแมธธอสชื่อเดิมแลว การสงผานตัวแปรจะตองเหมือนกันดวย ในบทที่เราแลวเรารูจกัการโอเวอรโหลดแมธธอส ขอใหสังเกตวาการโอเวอรโหลดกับการโอเวอรรายดมีความหมายตางกัน

ในกรณีของตัวแปรคลาส เราสามารถสรางตัวแปรคลาสช่ือเดิมในสับคลาสไดเหมือนกัน แตตัวแปรตัวใหมนี้จะไมทับตัวแปรตัวเกาที่นิยามไวในซูปเปอรคลาส เรายังสามารถอางถึงตัวแปรในซูปเปอรคลาสไดอยูดวยการใชคําวา superตามดวยจุดนําหนาชื่อตัวแปรดังตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 17 17 17 17 ---- 5 5 5 5 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

C:\java> java BuildACarI am a running car.

Page 131: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

131

class Vehicle {

int numberOfWheels;boolean hasEngine;

Vehicle() { // (1)numberOfWheels = 6;hasEngine = true;

}

void run(){System.out.println(“I am running”);

}

}

class PrivateCar extends Vehicle {

int numberOfPassengers;int numberOfWheels; // (2)

PrivateCar() { // (3)numberOfPassengers = 5;numberOfWheels = super.numberOfWheels - 2; // (4)

}

void playCD() {super.run(); // (5)System.out.println(“CD is playing.”);

}

void run() { // (6)System.out.println(I am a running car.”);

}

}

public class BuildACar {public static void main(String[] args) {

PrivateCar toyota = new PrivateCar();System.out.println(toyota.numberOfWheels);toyota.playCD();

}}

บรรทัด (1) คือ คอนสตรัคเตอรของ Vehicle ซึ่งเรากําหนดคาเริ่มตนใหตัวแปร numberOfWheels เปน 6 ตัวแปร numberOfWheels พรอมทั้งคาของมันจะสืบทอดไปยังสับคลาส PrivateCar

Page 132: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

132

บรรทัด (2) เราสรางตัวแปรคลาสช่ือเดิมใหกับคลาส PrivateCar แตในคอนสตรัคเตอรของ PrivateCarในบรรทัด (3) เรายังสามารถอางถึงตัวแปร numberOfWheels ที่นิยามไวในคลาส Vehicle ไดอยูดวยการ

ใช super. นําหนา โดยในกรณีนี้เรานํามามันกําหนดคาใหกับ numberOfWheels ตัวใหม เมือ่รันโปรแกรมจะไดคาของ numberOfWheels ตัวใหมเปน 4 เพราะถูกหักออก 2 ดังภาพ

สังเกตวาเราใชคําวา super เรียกตัวแปรคลาสของซูปเปอรคลาสไดเฉพาะในตัวสับคลาสเทาน้ัน ไมมีวิธีเรียกตัวแปรคลาสของซูปเปอรคลาสนอกตัวซับคลาส เชนการเรียกผานอินสแตนท

เชนเดียวกัน เราสามารถใชคําวา super ในการเรียกแมธธอสของซูปเปอรคลาสท่ีถูกโอเวอรรายดไปแลวได อยางเชนในบรรทัด (6) เราโอเวอรรายดแมธธอส run() ไปแลว แตเรายังสามารถเรียกใชงานแมทธธอสรันตัวเกาไดในบรรทัด (5)ดวยการใชคําวา super นําหนา ผลที่ไดคือจาวาเวอรชัวนแมทชีนจะรันแมธธอส run() ของซูปเปอรคลาสในแมธธอส playCD() ผลที่ไดจึงเปนดังภาพขางตน

การใชคําสั่ง super เรียกแมธธอสของซูปเปอรคลาสทําไดเฉพาะภายในตัวซับคลาสเทาน้ัน ไมมีวิธีเรียกแมธธอสของซูปเปอรคลาสภายในนอกตัวแมธธอส

ขอสังเกตเก่ียวกับ super ก็คือวา super ใชเรียกตัวแปรและแมธธอสของซูปเปอรคลาสที่อยูถัดขึ้นไปหนึ่งระดับเทาน้ัน ถามีการสรางสับคลาสมากกวาหนึ่งระดับเราไมมีวิธีเรียกตัวแปรและแมธธอสของซูปเปอรที่อยูถัดขึ้นไปกวาซูปเปอรคลาสท่ีอยูในระดับติดกับตัวสับคลาสได ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 17 17 17 17 ---- 6 6 6 6 : TestSuper.java: TestSuper.java: TestSuper.java: TestSuper.java

class A {

void x() { // (1)System.out.print(“I am in A.”);

}}

class B extends A {

void x() { // (2)System.out.println(“I am in B.”);

}}

C:\java> java BuildACar4I am running.CD is playing.

Page 133: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

133

class C extends B {

void x() { // (3)System.out.println(“I am in C.”);

}

void y() {super.x(); // (4)

}}

public class TestSuper {public static void main(String[] args) {

C c = new C();c.y(); // (5)

}}

คลาส C สืบทอดคลาส B ซ่ึงสืบทอดคลาส A มากอน ทั้งสามคลาสมีแมธธอสชื่อ x() อยูทั้งสิ้น หรืออีกนัยหน่ึงก็คือ x() ถูกโอเวอรรายดมาโดยตลอด ในบรรทัด (4) แมธธอส y() มีการเรียกแมธธฮส x() โดยใช superนําหนา ผลที่ไดคือเมื่อรันแมธธอส y() ในบรรทัด (5) จะไดแมธธอสในคลาส B ที่นิยามไวในบรรทัด (2)เพราะคลาส B เปนซูปเปอรคลาสตัวท่ีใกลชิดคลาส c มากที่สุด ดังในภาพ

แมธธอสถาวรแมธธอสถาวร คือ แมธธอสที่กําหนดใหไมสามารถสับคลาสไมสามารถนําไปโอเวอรรายดได เราประกาศใหแมธธอสเปนแมธธอสถาวรไดโดยใชคําสั่งวา final ตัวอยางเชน

final void x() {

}

เคล็ดลับ แมธธอสถาวร คือ แมธธอสที่โอเวอรรายดไมได ตัวแปรถาวร คือตัวแปรที่เปลี่ยนคาอีกไมได

C:\java> java BuildACarI am in B.

Page 134: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

134

คลาสถาวร คือ คลาสท่ีคลาสอ่ืนสืบทอดไมไดทั้งสามกรณีแมวาจะใชคําสั่ง final ในการประกาศเหมอืนกัน แตจุดมุงหมายตางกัน

แมธธอสนามธรรมแมธธอสนามธรรม คือ แมธธอสที่มีแตชื่อ ไมมีนิยาม เราใชคําวา abstract นําหนาชื่อแมธธอส และแทนที่จะมีบลอคปกกาตอทายชื่อ กลับมีแตเครื่องหมาย ; เทาน้ัน ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 17 17 17 17 ---- 7777 : TestAbstract.java: TestAbstract.java: TestAbstract.java: TestAbstract.java

abstract class A {void x() { }abstract y();

}

class B extends A {y() { };

}

คลาสที่มีแมธธอสนามธรรมอยูตองในคลาสนามธรรมเทานั้น และสับคลาสท่ีสืบทอดคลาสน้ีตองโอเวอรรายดแมธธอสนามธรรมท้ังหมดท่ีมีอยูในคลาสนามธรรมน้ันเพ่ือเปนการสรางนิยามใหแมธธอสเหลานั้น หรือมิฉะน้ันสับคลาสเหลานั้นตองถูกกําหนดใหเปนคลาสนามธรรมดวย เพื่อรอใหสับคลาสในรุนตอไปมานิยามแมธธอสนามธรรมเหลานั้นให ดังในตัวอยาง คลาส B ตองมีแมธธอส y() มิฉะนั้นคอมไพลเลอรจะไมยอมใหผาน นอกเสียจากจะประกาศใหคลาส B เปนคลาสนามธรรมเพ่ือรอใหคลาสอ่ืนมาสืบทอดแมธธอสนามธรรม y() ตอไป

เชนเดียวกันกับกรณีของคลาส แมธธอสนามธรรมไมสามารถถูกกําหนดใหเปนถาวรแมธธอสได และถาวรแมธธอสก็ไมสามารถถูกกําหนดใหเปนแมธธอสนามธรรมได

การเรียกคอนสตรัคเตอรของซูปเปอรคลาสในคอนสตรัคเตอรนอกจากเราจะใชคําส่ัง this() ในการเรียกคอนสตรัสเตอรตัวอ่ืนในคลาสเดียวกันแลว เรายังสามารถใชคําสั่ง super() ในการเรียกคอนสตรัคเตอรของซูปเปอรคลาสไดดวย ลองพิจารณาตัวอยางตอไปนี้

Page 135: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

135

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 17171717---- 8 8 8 8 : TestSuper.java: TestSuper.java: TestSuper.java: TestSuper.java

class A {

int a; // (1)

A() { // (2)System.out.println(“A : Default Constructor”);

}

A(int a) { // (3)this.a = a;System.out.println(“A : Constructor No. 1”);

}}

class B extends A {

B() { // (4)System.out.println(“B : Default Constructor”);

}

B(int b) {super(b); // (5)System.out.println(“B : Constructor No. 1”);

}}

public class TestSuper {public static void main(String[] args) {

B b = new B(); // (6)B c = new B(3); // (7)

}}

ผลการรันโปรแกรมขางตนเปนดังในภาพ

C:\java> java TestSuperA : Default ConstructorB : Default ConstructorA : Constructor No. 1B : Constructor No. 1

Page 136: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

136

ในโปรแกรมน้ีคลาส B สืบทอดคลาส A ทัง้สองคลาสมคีอนสตรัคเตอรสองคอนสตรัสเตอรคือคอนสตรัคเตอรปกติที่ไมมีการสงผานตัวแปร และคอนสตรัคเตอรท่ีมีการสงผานตัวแปรหน่ึงตัว

ในบรรทัด (5) คอนสตรัคเตอรท่ีมีการสงผานตัวแปรของคลาส B ใชคําสั่ง super(b) เพ่ือเรียกคอนสตรัคเตอรท่ีมีการสงผานตัวแปรของซูปเปอรคลาสของมันคือคลาส A

โปรแกรมเร่ิมจากสรางอินสแตนทของคลาส B ที่ชื่อ b ในบรรทัด (6) ดวยการเรียกคอนสตรัคเตอรแบบปกติในบรรทัด (4) คุณอาจแปลกใจเม่ือดูท่ีผลการรัน เพราะคอนสตรัคเตอรท่ีถูกเรียกกอนคอนสตรัคเตอรปกติของคลาส B คือคอนสตรัคเตอรปกติของคลาส A ที่เปนเชนนี้เปนเพราะความจริงแลวทุก ๆคอนสตรัคเตอรเวลาคอมไพล คอมไพลเลอรจะแอบใสคําส่ัง super() ไวที่บรรทัดแรก ทําใหมีการเรียกคอนสตรัคเตอรของซูปเปอรคลาสกอนท่ีจะทําอะไรอยางอ่ืนในคอนสตัคเตอรของตัวเอง ลองพิจารณาโปรแกรมขางลางนี้

Class A {A() {}

}

Class B extends A {B() {}

}

เวลาคอมไพล คอมไพลจะแอบใสคําสั่ง super() ลงไปดงน้ี

Class A{A() { super(); }

}

Class B extends A {B() { super(); }

}

ดังน้ันจะมีการรันคอนสตรัคเตอรของซูปเปอรคลาสกอนจะรันของตัวเอง และถามีการสืบทอดมากกวาหน่ึงระดับ จะมีการเรียกคอนสตรัคเตอรยอนตนข้ึนไปเร่ือย ๆ และจะรันคอนสตรัคเตอรของซูปเปอรคลาสบนสุดกอนเรียงไลลําดับลงมาจากบนลงลาง

ในบรรทัด (7) มีการเรียกคอนสตรัคเตอรแบบมีการสงผานตัวแปรของคลาส B ในบรรทัด (5) ในกรณีน้ีเราใสคําส่ัง super(b)ซ่ึงเปนการเรียกคอนสตรัคเตอรของซูปเปอรคลาสแบบมีตัวแปรสงผาน คอมไพลเลอรจะไมแอบใสคําส่ัง super() อีก โปรแกรมจะเรียกคอนสตรัคเตอรในบรรทัด (3) แลวคอยรันคอนสตรัสเตอรในบรรทัด (5) ดังที่เห็นในผลการรัน

คําส่ัง super() มีใชไดในคอนสตรัคเตอรเทานั้น และตองเปนคําส่ังแรกสุดดวย ซึ่งก็หมายความวาคําสั่ง super() ไมสามารถอยูรวมกับคําสั่ง this() ได เพราะตางก็ตองเปนคําส่ังแรกสุดของคอนสตรัคเตอร

Page 137: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

137

ในกรณีที่ซูปเปอรคลาสไมมีการนิยามคอนสตรัคเตอรปกติแบบไมมีตัวแปรสงผานเอาไว แตมีการนิยามคอนสตรัคเตอรแบบมีตัวแปรสงผาน คอนสตรัคเตอรของสับคลาสของมันจาํเปนตองเรียกคอนสตรัคเตอรของซูปเปอรคลาสแบบมีตัวแปรสงผานดวยคําสั่ง super() มิฉะน้ันเวลาคอมไพล คอมไพลเลอรจะแอบใสคําส่ัง super() ลงไป ทําใหคอมไพลไมผานเพราะคอนสตรัคเตอรปกติไมมีในซูปเปอรคลาส ตัวอยางเชน

Class A {A(int a) {}

}

Class B extends A {B() {

super(a); // (1)}

}

คําส่ังบรรทัด (1) ตองมีไวเสมอ จะละไมไดเปนอันขาด

เคล็ดลับ เพื่อปองกันปญหาขางตนผูรูบางคนบอกวา หลักการเขียนคลาสท่ีดีตองนิยามคอนสตรัคเตอรปกติไวดวยเสมอ แมวาจะไมมีคําสั่งอะไรอยูในนั้นเลยก็ตาม และฝกใหเปนนิสัย

การแปลงรูปตัวแปรอางอิงของซูปเปอรคลาสสามารถใชช้ีซับคลาสไดดวย ดงตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 17 17 17 17 ---- 9 9 9 9 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;

void run(){System.out.println(“I am running”);

}

}

class Truck extends Vehicle {

float maximumLoad;

void load(float weight) {if (weight <= maximumLoad)

Page 138: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

138

System.out.println(“I am carrying a “ + weight + “-poundload.”);}

}

class PrivateCar extends Vehicle {

int numberOfPassengers;

void playCD() { // (6)System.out.println(“CD is playing.”);

}}

public class BuildACar {public static void main(String[] args) {

Vehicle v = new Vehicle(); // (1)Truck isuzu = new Truck(); // (2)PrivateCar toyota = new PrivateCar();// (3)v = isuzu; // (4)toyota = isuzu; // (5) Errorisuzu = new Vehicle(); // (6) Error

}}

โปรแกรมน้ีมีซูปเปอรคลาสช่ือ Vehicle ซึ่งเปนแมแบบของซับคลาส Truck และ PrivateCar

ในแมธธอส main() เราประกาศตัวแปรอางอิงของท้ังสามคลาสในบรรทัด (1) (2) (3) ตามลําดับ จากน้ันเราเปล่ียนใหตัวแปรอางอิง v มีคาเทากับตําแหนงในแรมของตัวแปรอางอิง isuzu ในบรรทัด (4) ซ่ึงสามารถทําไดเพราะตัวแปรอางอิงของซูปเปอรคลาสสามารถใชช้ีอินสแตนทของซับคลาสได คุณสมบัตินี้มีเหตุผลตามหลักสามัญสํานึกเพราะ ตัวแปรอางอิง v มีไวชี้รถยนต ดังนั้นมันควรจะสามารถใชชี้รถบรรทุกไดดวย เพราะรถบรรทุกก็เปนรถยนต

ในบรรทัด (5) เราพยายามกําหนดคาของตัวแปรอางอิง toyota ใหชี้ไปที่ตําแหนงของอินแสตนทของรถบรรทุก คอมไพลเลอรจะฟองความผิดพลาดออกมาเพราะตัวแปรอางอิง toyota ไมใชตัวแปรอางอิงรถยนต และไมใชตัวแปรอางอิงรถบรรทุก จึงไมสามารถใชชี้อินสแตนทของรถบรรทุกได

ในบรรทัด (6) เราพยายามกําหนดคาของตัวแปรอางอิง isuzu ใหชี้อินสแตนทของคลาส Vehicle ที่สรางขึ้นมาใหม คอมไพลเลอรจะฟองความผิดพลาดออกมาเพราะตัวแปรอางอิง isuzu เปนตัวแปรอางอิงที่ใชชี้รถบรรทุกเทานั้น ไมควรนํามาชี้อินสแตนทของ Vehicle

Page 139: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

139

สรุปก็คือตัวแปรอางอิงของซูปเปอรคลาสสามารถช้ีอินสแตนทของสับคลาสไดดวย แตตัวแปรอางอิงของสับคลาสไมสามารถใชช้ีอินสแตนทของซูปเปอรคลาสหรืออินสแตนทของคลาสท่ีมีซูปเปอรคลาสเดียวกันได และแนนอนถาจะลองนําไปช้ีคลาสอ่ืน ๆ ที่ไมมีความเกี่ยวของกันเลยก็ยิ่งไมไดใหญ

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

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 17 17 17 17 ---- 10 10 10 10 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;

void run(){System.out.println(“I am running”);

}

}

class Truck extends Vehicle {

float maximumLoad;

void load(float weight) {if (weight <= maximumLoad)System.out.println(“I am carrying a “ + weight + “-pound

load.”);}

}

class PrivateCar extends Vehicle {

int numberOfPassengers;

void playCD() {System.out.println(“CD is playing.”);

}}

class Mechanic {void removeWheels(Vehicle v) { // (1)

v.numberOfWheels = 0;}

}

public class BuildACar {

Page 140: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

140

public static void main(String[] args) {Truck isuzu = new Truck(); // (2)PrivateCar toyota = new PrivateCar();// (3)Mechanic robert = new Mechanic(); // (4)robert.removeWheels(isuzu); // (5)robert.removeWheels(toyota); // (6)System.out.println(“isuzu has ” + isuzu.numberOfWheels + “

wheels.”);System.out.println(“toyota has ” + toyota.numberOfWheels + “

wheels.”);

}}

สิ่งใหมในโปรแกรมนี้คือคลาส Mechanic ซ่ึงก็คือชางเคร่ือง ชางเครื่องในโปรแกรมนี้มีความสามารถหนึ่งอยางคือการสามารถถอดลอรถยนตได ดังจะเห็นไดจากแมธธอสชือ่ removeWheels() ในบรรทัด (1) แมธธอส removeWheels() มีการสงผานตัวแปรหนึ่งตวไดแกตัวแปรอางอิง v ซึ่งเปนตัวแปรอางอิงที่ใชชี้รถยนต

ในบรรทัด (2) (3) ในแมธธอส main() เราสรางอินสแตนทของรถบรรทุก และรถเกงขึ้นมา เราตองการถอดลอรถท้ังสองคันน้ี เราจึงสรางอินสแตนทของชางเครื่องขึ้นมาชื่อ robert ในบรรทัด (4)

ในบรรทัด (5) (6) เราสามารถเรียกแมธธอส removeWheels() ของโรเบิรตขึ้นมาถอดลอของทั้งรถบรรทุกและรถเกงไดเพราะตัวแปรอางอิง v ที่สงผานเขาไปในแมธธอส removeWheels() ใชชี้ไดทั้งอินสแตนทของรถบรรทุกและรถเกง ถาไมมีคุณสมบัติการแปรรูปเชนนี้ในภาษาจาวา เราคงตองเขียนแมธธอสในการถอดลอขึ้นมาเฉพาะสําหรับรถแตละประเภท ทําใหโปรแกรมมีความซ้ําซอนไมกระชับ นี่คือประโยชนที่สําคัญมากของการแปรรูป

ผลการรันโปรแกรมเปนดังภาพขางลาง รถท้ังสองคันถูกถอดลอ

การแปรรูปเปนคุณสมบัติที่มีประโยชน อยางไรก็ตามปญหาจะเกิดขึ้นในกรณีที่มีการโอเวอรรายดแมธธอส ลองพิจารณาตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 17 17 17 17 ---- 11 11 11 11 : TestACar.java: TestACar.java: TestACar.java: TestACar.java

class Vehicle {

int numberOfWheels;

C:\java> java BuildACarisuzu has 0 wheels.toyota has 0 wheels.

Page 141: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

141

boolean hasEngine;

Vehicle() {numberOfWheels = 10; // (1)

}

void run(){ // (2)System.out.println(“I am running”);

}

}

class PrivateCar extends Vehicle {

int numberOfWheels;int numberOfPassengers;

PrivateCar() { // (3)numberOfWheels = 4;}

void playCD() { // (4)System.out.println(“CD is playing.”);

}

void run() { // (5)System.out.println(“I am a running private car.”);

}}

public class BuildACar {public static void main(String[] args) {

Vehicle v = new PrivateCar(); // (6)v.playCD(); // (7) Errorv.run(); // (8)System.out.println(“v has “ + v.numberOfWheels + “ wheels.”);// (9)

}}

ในบรรทัด (5) สับคลาส PrivateCar มีการโอเวอรรายดแมธธอส run() ของซูปเปอรคลาส Vehicle

โปรแกรมเริ่มตนที่แมธธอส main() ในบรรทัด (6) ดวยการประกาศตัวแปรอางอิงชื่อ v โดยกําหนดใหชี้อินสแตนทของคลาส PrivateCar เมือ่เรียกแมธธอส playCD() ในบรรทัด (7) คอมไพลเลอรจะฟองความผิดพลาดออกมาเพราะถึงแมวาตัวแปรอางอิง v จะชี้อินสแตนทของคลาส PrivateCar แตตัวมันเองเปนที่รูจักในฐานะของตัวชี้อินสแตนทของคลาส Vehicle ซึ่งไมมีแมธธอสชื่อ playCD() อยู

Page 142: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

142

แตในกรณีท่ีสับคลาสมีการโอเวอรรายดแมธธอสของซูปเปอรคลาส คอมไพลเลอรยอมรูจักแมธธอสนั้นเพราะมันพบช่ือแมธธอสในซูปเปอรคลาส ดังนั้นโปรแกรมจะคอมไพลผาน เชนในกรณีของแมธธอส run() ที่ถูกเรียกในบรรทัด (8) อีกทั้งเมื่อเวลารันโปรแกรมจาวาเวอรชัวนแมทชีนจะรูจักรันแมธธอสในสับคลาสใหดวย ผลท่ีไดก็คือโปรแกรมขางตนจะรันแมธธอส run() ในบรรทัด (5) แทนที่จะเปนบรรทัด (2) ดังในภาพ

แตในกรณีของตัวแปรอินสแตนท สถานการณจะกลับกับกรณีของแมธธอส ถามีการประกาศตัวแปรชื่อเดิมในสับคลาสแทนที่จาวาเวอรชัวนแมทชีนจะรูจักตัวแปรตัวใหมในสับคลาส มันจะใชตัวแปรตัวเกาในซูปเปอรคลาส หรืออีกนัยหนึ่ง จาวาเวอรชัวนแมทชีนจะดูชนิดของตัวแปรอางอิงเปนสําคัญในกรณีของตัวแปรอินสแตนท สวนในกรณีของแมธธอสอินสแตนทจาวาเวอรชัวนแมทชีนจะดูชนิดของอินสแตนทเปนสําคัญ ดังในตัวอยางมีการกําหนดคาเริ่มตนให numberOfWheels เปน 10 ในคอนสตรัคเตอรของซูปเปอรคลาส Vehicle ในบรรทัด (1) และกําหนดคาเริ่มตนให numberOfWheels เปน 4 ในคอนสตรัคเตอรของสับคลาส PrivateCar ในบรรทัด (3) พอเรียกตัวแปร numberOfWheels ออกมาแสดงคาในบรรทัด (9)ผลท่ีไดคือ 10 แทนที่จะเปน 4

ในบางกรณีเราอาจเคยกําหนดตัวแปรอางอิงสําหรับซูปเปอรคลาสใหช้ีอนิสแตนทของสับคลาส แลวตองการใชอินสแตนทนั้นในการกําหนดคาใหกับตัวแปรอางอิงสําหรับสับคลาสตัวหนึ่ง เราสามารถทําไดดวยการแคสในลักษณะเดียวกันกับการแคสตัวแปรพ้ืนฐาน ลองดูตัวอยางตอไปน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 17 17 17 17 ---- 12 12 12 12 : TestACar.java: TestACar.java: TestACar.java: TestACar.java

class Vehicle {

int numberOfWheels=10;boolean hasEngine;

void run(){System.out.println(“I am running”);

}

}

class PrivateCar extends Vehicle {

int numberOfWheels=4;int numberOfPassengers;

C:\java> java TestACarI am running a private car.v has 10 wheels.

Page 143: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 17 การสืบทอด

143

void playCD() {System.out.println(“CD is playing.”);

}

void run() {System.out.println(“I am a running private car.”);

}

}

public class TestACar {public static void main(String[] args) {

Vehicle v = new PrivateCar(); // (1)PrivateCar p = (PrivateCar) v; // (2)p.playCD();p.run();System.out.println(“P has “ + p.numberOfWheels + “ wheels.”);

}}

ในบรรทัด (1) เราประกาศตัวแปรอางอิงแบบ Vehicle ขึ้นมาแลวกําหนดใหชี้อินสแตนทของคลาส PrivateCar จากนั้นในบรรทัด (2) เราก็นําตัวแปรอางอิงมาใชกําหนดคาใหตัวแปรอางอิง p ซ่ึงเปนตัวแปรอางอิงสําหรับอินสแตนทของคลาส PrivateCar แตเนื่องจาก v เปนตัวแปรอางอิงชนิด Vehicle เราจึงตองทําการแคสใหกลายเปน PrivateCar ดวยการเติม (PrivateCar) ไวหนา v เพื่อมิใหคอมไพลเลอรเขาใจผิดและฟองความผิดพลาดออกมา

ตัวแปรอางอิง p สามารถรันแมธธอสในคลาส PrivateCar และเรียกตัวแปรอินสแตนทของ PrivateCar

ไดเหมือนปกติทุกประการ

Page 144: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม
Page 145: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

18 แพจเกจ

ถาสังเกตดูใหดีจะพบวาซอรสโคดภาษาจาวาประกอบดวยนิยามของคลาสตั้งแตหนึ่งคลาสขึ้นไปเขียนเรียงตอกันไปเร่ือย ๆ โดยที่ตองมีคลาสคลาสหนึ่งในซอรสโคดที่มีชื่อเหมือนชื่อไฟลและมีแมธธอสชื่อ main() อยู เวลารันโปรแกรมจาวาเวอรชัวนแมทชีนจะมองหาคลาสคลาสนี้แลวเริ่มรันจากแมธธอส main()

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

ลองพิจารณาโปรแกรมตอไปนี้ซึ่งเปนโปรแกรมที่เราเคยผานมาแลว

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 18 18 18 18 ---- 1 1 1 1 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;

void run(){System.out.println(“I am running”);

Page 146: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 18 แพจเกจ

146

}

}

class Truck extends Vehicle {

float maximumLoad;

void load(float weight) {if (weight <= maximumLoad)System.out.println(“I am carrying a “ + weight + “-pound

load.”);}

}

class PrivateCar extends Vehicle {

int numberOfPassengers;

void playCD() {System.out.println(“CD is playing.”);

}}

class Mechanic {void removeWheels(Vehicle v) { // (1)

v.numberOfWheels = 0;}

}

public class BuildACar {

public static void main(String[] args) {Truck isuzu = new Truck(); // (2)PrivateCar toyota = new PrivateCar();// (3)Mechanic robert = new Mechanic(); // (4)

}}

โปรแกรมน้ีประกอบดวยคลาสหาคลาส คลาสส่ีคลาสแรกเปนคลาสท่ีสนับสนุนคลาสสุดทายคือคลาส BuildACarซึ่งเปนคลาสหลักที่มีแมธธอสชื่อ main() อยู

car

Vehicle Truck PrivateCar

Page 147: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 18 แพจเกจ

147

สมมติวาเราตองการยายคลาสสามคลาสแรกไปอยูในแพจเกจชื่อ car เราสามารถทําไดโดยการสรางไฟลสามไฟลตอไปน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 18 18 18 18 ---- 2 2 2 2 : Vehicle.java: Vehicle.java: Vehicle.java: Vehicle.java

package car;

public class Vehicle {

int numberOfWheels;boolean hasEngine;

void run(){System.out.println(“I am running”);

}

}

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 18 18 18 18 ---- 3 3 3 3 : Truck.java: Truck.java: Truck.java: Truck.java

package car;

public class Truck extends Vehicle {

float maximumLoad;

void load(float weight) {if (weight <= maximumLoad)System.out.println(“I am carrying a “ + weight + “-pound

load.”);}}

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 18 18 18 18 ---- 4 4 4 4 : PrivateCar.java: PrivateCar.java: PrivateCar.java: PrivateCar.java

package car;

public class PrivateCar extends Vehicle {

int numberOfPassengers;

Page 148: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 18 แพจเกจ

148

void playCD() {System.out.println(“CD is playing.”);

}}

ในบรรทัดแรกสุดของท้ังสามไฟลมีคําส่ัง

package car;

คําส่ังน้ีเปนการบอกวาคลาสท่ีอยูในซอรสโคดน้ีถูกจัดอยูในแพจเกจชื่อวา car คําส่ังน้ีตองเปนคําส่ังแรกสุดเสมอในซอรสโคดของแพจเกจ และการตั้งชื่อแพจเกจเรานิยมใชตัวอักษรภาษาอังกฤษพิมพเล็กทั้งหมด

ขอสังเกตอีกอยางหน่ึงก็คือ คราวน้ีเราตองเพ่ิมคําส่ัง public ไวหนาคลาสท้ังสามคลาส และตั้งชื่อไฟลใหเหมือนช่ือคลาส เพราะซอรสโคดของภาษาจาวาตองมีคลาสหน่ึงคลาสในไฟลเปน public และมีชื่อเหมือนชื่อไฟลเสมอ

คําวา public สามารถใชกํากับหนาคลาสอะไรก็ไดเพ่ือกําหนดใหคลาสน้ันเปน คลาสสาธารณะ คลาสสาธารณะคือคลาสที่สามารถถูกอางถึงไดในแพจเกจอื่น คลาสปกติสามารถอางถึงไดเฉพาะในแพจเกจที่มันอยูเทานั้น คลาสหลักของโปรแกรมเปนคลาสสาธารณะเสมอเพราะ

เวลาคอมไพลแพจเกจทั้งสามไฟลนี้ตองเริ่มคอมไพลจากไฟล Vehicle.java กอน เพราะคลาส Truck และ PrivateCar มีการอางถึงชื่อของคลาส Vehicle ดังน้ัน กอนจะคอมไพล Truck.java และ PrivateCar.java ไดคลาส Vehicle จะตองไปรออยูกอนแลวในแพจเกจ car ดังน้ันการคอมไพลคลาสท้ังสามตองทําตามลําดับดังนี้

สังเกตวาคราวน้ีเราเติมพารามิเตอร –d C:\java เขาไปในคําสั่งดวย พารามิเตอร –d เปนพารามิเตอรที่ใชบอกวาเมื่อคอมไพลเสร็จแลวใหเก็บไฟล .class ไวที่ไหน ซึ่งในกรณีนี้ใหเก็บไวที่ C:\java ถาลองใชคําสั่ง dir ดูจะพบโฟลเดอรชื่อ car ใต C:\java และถาลองเขาไปดูในโฟลเดอร car ก็จะพบไฟล Vehicle.class Truck.class และ PrivateCar.class อยู ตอนนี้ถือวาคลาสทั้งสามอยูภายใตแพจเกจ car เรียบรอยแลว

C:\java> javac –d C:\java Vehicle.java

C:\java> javac –d C:\java Truck.java

C:\java> javac –d C:\java PrivateCar.java

Page 149: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 18 แพจเกจ

149

น้ันคือเวลาสรางแพจเกจ คอมไพลเลอรจะสรางโฟลเดอรท่ีมีช่ือเหมือนแพจเกจ แลวเก็บคลาสท่ีเปนสมาชิกของแพจเกจเอาไวใตโฟลเดอรน้ัน ไฟลเหลาน้ีเปนไฟลนามสกุล .class ดังน้ันจึงเปนคลาสท่ีคอมไพลไวแลว เวลานําไปใชงานคอมไพลเลอรสามารถดึงไปใชงานไดเลยไมตองคอมไพลใหม

ทีนี้สมมติวาเราจะสรางโปรแกรมสวนที่เหลือใหเสร็จสมบูรณ เราสามารถอางถึงคลาสในแพจเกจไดทันที ไมตองเขียนซํ้าอีก ไฟลโปรแกรมของเราจึงเหลือแคสองคลาสสุดทายท่ีเราไมไดเลือกเอาไปไวในแพจเกจ

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 18 18 18 18 ---- 5 5 5 5 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

class Mechanic {void removeWheels(car.Vehicle v) { // (1)

v.numberOfWheels = 0;}

}

public class BuildACar {

public static void main(String[] args) {car.Truck isuzu = new car.Truck(); //(2)car.PrivateCar toyota = new car.PrivateCar(); //(3)Mechanic robert = new Mechanic();

}}

สังเกตส่ิงท่ีเปล่ียนไปก็คือ ทุกครั้งที่มีการอางถึงคลาสที่อยูในแพจเกจ เราตองระบุชื่อของแพจเกจกอนแลวตามดวยจุด ดังในบรรทัด (1) (2) (3)

เวลาจะคอมไพลไฟลโปรแกรมที่มีการใชคลาสในแพจเกจที่สรางไวแลว จําเปนที่จะตองบอกคอมไพลเลอรดวยวาแพจเกจถูกเก็บไวที่ไหน เราใชพารามิเตอร –classpath ในการระบุที่อยูของแพจเกจ ซึ่งในกรณีนี้เราเก็บแพจเกจไวที่C:\java\car คําส่ังในการคอมไพลจึงเปนดังน้ี

ถาเราไมตองการเขียนชื่อแพจเกจทุกครั้งที่มีการอางถึงคลาสในแพจเกจ เราทําไดโดยใชคําสั่ง import ดังน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 18 18 18 18 ---- 6 6 6 6 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

import car.Vehicle;import car.Truck;

C:\java> javac –classpath C:\java BuildACar.java

Page 150: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 18 แพจเกจ

150

import car.PrivateCar;

class Mechanic {void removeWheels(Vehicle v) { // (1)

v.numberOfWheels = 0;}

}

public class BuildACar {

public static void main(String[] args) {Truck isuzu = new Truck(); //(2)PrivateCar toyota = new PrivateCar(); //(3)Mechanic robert = new Mechanic();

}}

ที่ตนโปรแกรมเราใชคําสั่ง import ตามดวยชื่อเต็มของคลาสในแพจเกจ car ที่ตองมีการอางถึงในโปรแกรมของเราทุกคลาส คราวนี้เราก็ไมจําเปนตองระบุชื่อแพจเกจทุกครั้งที่มีการอางถึงคลาสเหลาน้ีในโปรแกรม ดงในบรรทัด (1) (2) (3)

เรายังสามารถยอคําส่ัง import ไดอีก เนื่องจากทุกคลาสที่เราอิมพอรตเขามาอยูในแพจเกจเดียวกันคือแพจเกจ car ดังน้ันเราสามารถอิมพอรตทุกคลาสในแพจเกจ car ไดดวยคําส่ังคําส่ังเดียวดังบรรทัด (1) ในโปรแกรมขางลางน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 18 18 18 18 ---- 7 7 7 7 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

import car.*; // (1)

class Mechanic {void removeWheels(Vehicle v) {

v.numberOfWheels = 0;}

}

public class BuildACar {

public static void main(String[] args) {Truck isuzu = new Truck();PrivateCar toyota = new PrivateCar();Mechanic robert = new Mechanic();

}}

Page 151: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 18 แพจเกจ

151

ผลท่ีไดของการสรางแพจเกจก็เหมือนกับการคอมไพลไฟลท่ีมีคลาสท้ังหาคลาสอยูในไฟลเดียว แตมีขอดีคือ ถาเราตองการเขียนโปรแกรมอื่น ที่ตองใชคลาส Vehicle Truck หรือ PrivateCar ดวย เราสามารถ importคลาสเหลาน้ันเขามาในซอรสโคดของเราไดทันทีโดยท่ีไมตองเขียนนยิามของคลาสเหลาน้ีซํ้าอีกในซอรสโคดของเรา คอมไพลเลอรจะดึงคลาสเหลาน้ันท่ีคอมไพลไวแลวไปใชไดทันที

สับแพจเกจ

การเก็บคลาสไวในแพจเกจสามารถจัดเปนหมวดหมูแบบตนไมไดดวย ตัวอยางเชน แทนที่เราจะจัดคลาส VehicleTruck และ PrivateCar ไวในแพจเกจเดียวกัน เราอาจจัดไลระดับกลาวคือ ให Vehicle อยูในแพจเกจ car สวน Truck และ PrivateCar อยูในแพจเกจ type ซึ่งอยูใตแพจเกจ car อีกที เราเรียกแพจเกจ type วาเปน สับแพจเกจ ของแพจเกจ car ถาเราตองการจัดคลาสในลักษณะท่ีกลาวมาน้ี ซอรสโคดท่ีเราสรางจะเปนดงน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 18 18 18 18 ---- 8 8 8 8 : Vehicle.java: Vehicle.java: Vehicle.java: Vehicle.java

package car;

public class Vehicle {

int numberOfWheels;boolean hasEngine;

void run(){System.out.println(“I am running”);

}

}

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 18181818 ---- 9999 : Truck: Truck: Truck: Truck.java.java.java.java

package car.type;

car

typeVehicle

Truck PrivateCar

Page 152: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 18 แพจเกจ

152

import car.Vehicle;

public class Truck extends Vehicle {

float maximumLoad;

void load(float weight) {if (weight <= maximumLoad)System.out.println(“I am carrying a “ + weight + “-pound

load.”);}

}

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 18181818 –––– 10 10 10 10 : PrivateCar.java : PrivateCar.java : PrivateCar.java : PrivateCar.java

package car.type;

import car.Vehicle;

public class PrivateCar extends Vehicle {

int numberOfPassengers;

void playCD() {System.out.println(“CD is playing.”);

}}

ไมมีอะไรเปลี่ยนแปลงในไฟล Vehicle.java เพราะเราเลือกใหคลาส Vehicle อยูในแพจเกจ car เหมือนเดิม

ในไฟล Truck.java และ PrivateCar.java เราเปลี่ยนชื่อของแพจเกจเปน car.type ซึ่งหมายความวาแพจเกจนี้ชื่อแพจเกจ type และเปนสับแพจเกจของแพจเกจ car

เราตอง import คลาส car.Vehicle ดวย เพราะคราวน้ีคลาส Vehicle อยูคนละแพจเกจกับคลาส Truck และ PrivateCar แลว แมวา type จะเปนสับแพจเกจของ car แตไมไดหมายความวาแพจเกจ type จะเขาถึงแพจเกจ car ได ลองพิจารณาคําส่ังตอไปน้ี

import car.*;

คําส่ังน้ีอิมพอรตเฉพาะ car.Vehicle เทาน้ัน ไมรวม car.type.Truck และ car.type.PrivateCarถาตองการอิมพอรตท้ังสามคลาสควรเขียนเปน

Page 153: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 18 แพจเกจ

153

import car.*;import car.type.*;

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

คราวนี้เวลาคอมไพลใหใชคําสั่งดังนี้

สังเกตวาคราวน้ีเราตองระบุ classpath ใหไฟล Truck.java และ PrivateCar.java ดวย เพราะไฟลท้ังสองมีการอิมพอรตคลาส Vehicle

สวนเวลาคอมไพลโปรแกรมก็ทําไดเหมือนเดิม อยาลืมอิมพอรตแพจเกจ car.type ดวยดังบรรทัด (1) ขางลางน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 18 18 18 18 ---- 11 11 11 11 : BuildACar.java: BuildACar.java: BuildACar.java: BuildACar.java

import car;import car.type.*; // (1)

class Mechanic {void removeWheels(Vehicle v) {

v.numberOfWheels = 0;}

}

public class BuildACar {

public static void main(String[] args) {Truck isuzu = new Truck();PrivateCar toyota = new PrivateCar();Mechanic robert = new Mechanic();

}}

C:\java> javac –d C:\java Vehicle.java

C:\java> javac –d C:\java –classpath C:\java Truck.java

C:\java> javac –d C:\java –classpath C:\java PrivateCar.java

Page 154: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 18 แพจเกจ

154

เวลาคอมไพลก็ส่ังดังน้ี

นักเขียนโปรแกรมที่ทํางานจริง ๆ อาจใชแพจเกจที่คนอื่นเขียนขึ้นชวยในการเขียนโปรแกรมของตัวเอง ดังน้ันโปรแกรมหนึ่ง ๆอาจมีการอิมพอรตคลาสจากแพจเกตจํานวนมาก ประโยชนอยางหนึ่งของการเก็บคลาสไวเปนแพจเกจก็คือการปองกันปญหาในกรณีท่ีมีการต้ังช่ือคลาสซํ้า ๆกัน ซึ่งโดยทั่วไปจะนิยมตั้งชื่อแพจเกจตามชื่อบริษัท เชน แพจเกจที่เขียนโดยบริษัท Oracle อาจตั้งชื่อแพจเกจหลักวา com.oracle แลวสรางสับแพจเกจจํานวนมากเทาไรก็ไดตามใชชอบ เชน com.oracle.util, com.oracle.sql, com.oracle.sql.query

เปนตน

สมมติวาในสับแพจเกจ com.oracle.util มีคลาสชื่อ ToString อยู แตบังเอิญนักเขียนโปรแกรมคนเดียวกันใชแพจเกจของบริษัท BEA ชื่อ com.bea ซ่ึงมีคลาสช่ือ ToString อยู เราตองเขียนชื่อเต็มของคลาสทุกครั้งเพื่อเปนการแยกแยะความแตกตางแมวาเราจะอิมพอรตแลวก็ตาม ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 18 18 18 18 ---- 12 12 12 12 : MyProgram.java: MyProgram.java: MyProgram.java: MyProgram.java

import com.oracle.util.*;import com.bea.*;

public class MyProgram {

public static void main(String[] args) {com.oracle.util.ToString tostr1 = newcom.oracle.util.ToString();

com.bea.ToString tostr2 = new com.bea.ToString();

}}

C:\java> javac –classpath C:\java BuildACar.java

Page 155: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 18 แพจเกจ

155

แพจเกจมาตรฐานในภาษาจาวามีแพจเกจมาตรฐานกลุมหนึ่งซึ่งเก็บคลาสพื้นฐานของภาษาจาวาเอาไวใหนักเขียนโปรแกรมเมอรภาษาจาวาอิมพอรตไปใชไดเลย ตัวอยาง ของแพจเกจที่ควรรูจักไดแก

java.lang

แพจเกจนี้เปนแพจเกจพื้นฐานที่สุดของภาษาจาวา ตัวอยางคลาสในแพจเกจนี้ไดแก คลาส Math คลาส Stringคลาสของตัวแปรพ้ืนฐาน คลาสเก่ียวกับเอ็กซเซฟช่ัน และคลาสเก่ียวกับ เทรด เวลาตองการใชงานคลาสในแพจเกจนี้ไมตองใชคําสั่ง import สามารถนําไปใชไดทันที

java.util

แพจเกจน้ีเก็บคลาสเก่ียวกับการจัดการวันท่ี โซนเวลา การจัดการขอมูล ภาษาตางประเทศ เวลาตองการใชงานคลาสในแพจเกจนี้ตองใชคําสั่ง import java.util.*;

java.io

แพจเกจน้ีเก็บคลาสเก่ียวกับการเขียนอานดิสก การรับคาคียบอรด และการแสดงผลออกนอกจอ เวลาตองการใชงานคลาสในแพจเกจนี้ตองใชคําสั่ง import java.io.*;

ถาตองการทราบวาคลาสในแพจเกจนี้มีอะไรบาง สามารถคนควาไดจากเวบไซต http://java.sun.com การรวมคลาสและแมธธอสหลาย ๆอันไวในแพจเกจนี้ก็คลาย ๆกับการพัฒนา API เปนกลุม ๆน้ันเอง

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

เพื่อใหการเชื่อมงานแตละสวนเขาดวยกันทําไดงาย นักเขียนโปรแกรมแตละคนจะเขียนโปรแกรมในสวนที่ตัวเองรับผิดชอบเปนคลาส และเก็บคลาสเหลาน้ันไวในแพจเกจ จากนั้นก็ประชาสัมพันธออกไปใหเพื่อนรวมงานทราบวา แพจเกจของตนชือ่อะไร มีคลาสและแมธธอสอะไรใหใชบาง เพ่ือนรวมงานแครูวาจะเรียกแมธธอสในคลาสเหลาน้ันไดอยางไร และคลาสเหลาน้ันทําอะไรไดบางก็พอ เพื่อนรวมงานจะไมสนใจวาคลาสและแมธธอสเหลานั้นสรางขึ้นไดอยางไร หรือมีเนื้อหาขางในเปนอยางไรบาง เพราะงานสวนท่ีพวกเขารับผิดชอบก็นาปวดหัวพออยูแลว

วิธีการแบบนี้ลดความนาปวดหัวเวลาทํางานรวมกันลง ทุกคนท่ีสรางคลาสจะซอนรายละเอียดในการสรางคลาสเอาไว และประชาสัมพันธใหคนอื่นทราบแตเฉพาะ วิธีการเรียกใชคลาสเหลาน้ันเทาน้ัน ซ่ีงก็คือ คลาสน้ันช่ืออะไร มีตัวแปรคลาสอะไร มีแมธธอสอะไร ทําอะไรได เวลาเรียกตองสงผานตัวแปรอะไรเขาไป แลวจะไดตัวแปรอะไรกลับออกมา ขอ

Page 156: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 18 แพจเกจ

156

มูลเหลาน้ีเราเรียกวา คอนแทร็คของคลาสหรือแมธธอส สวนรายละเอียดภายในคลาสท่ีเราซอนไวไมใหคนอ่ืนเห็นเรียกวา อิมพลีเมนทเทชั่นของคลาส หรือแมธธอส

ตัวอยางเชน นักเขียนโปรแกรมคนหนึ่งเขียนแมธธอสสแตรติกอันหนึ่งขึ้นมา ดังน้ี

public static int squareRoot(int i) {return i * i;

}

คอนแทร็คของแมธธอสนี้คือ

public static int squareRoot(int i)

อิมพลีเมนทเทชั่นของแมธธอสนี้คือ

{ return i*i; }

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

public static int squareRoot(int)

และอาจมีคําอธิบายวาแมธธอสน้ีใชทําอะไร แคนี้ผูอานคูมือก็รูแลววาจะเรียกแมธธอสนี้ทําอะไรและจะเรียกแมธธอสน้ีไดอยางไร สวนอิมพลีเมนทเทชั่นของแมธธอสนั้นผูอานไมสนใจ

Page 157: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

19 ตัวกํากับตัวแปรคลาสและแมธธอส

ปกติแลวคลาสที่เราสรางขึ้นมาจะสามารถถูกอางถึงไดภายในตัวมันเอง และภายในคลาสอ่ืน ๆ ที่อยูในแพจเกจเดียวกัน ถาเราตองการใหคลาสในแพจเกจอ่ืน ๆอางถึงคลาสท่ีเราสรางข้ึนไดดวยเราจะประกาสคลาสน้ันใหเปน คลาสสาธารณะ ดวยการใชคําสั่ง public

เราสามารถกําหนดขอบเขตของการเขาถึงตัวแปรคลาส และ แมธธอส ไดในทํานองเดียวกันกับการใชคําส่ัง publicในกรณีของคลาส แตคําสั่งสําหรับตัวแปรคลาส และ แมธธอส มีมากกวาแคคําสั่ง public เราเรียกคําส่ังเหลาน้ีวา ตัวกํากับตัวแปรคลาส และแมธธอส

คําส่ัง Privateโดยปกติแลวทั้งตัวแปรคลาส และแมธธอส สามารถถูกอางถึงไดท้ังในและนอกคลาส ลองพิจารณาตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 19 19 19 19 ---- 1 1 1 1 : TestACar.java: TestACar.java: TestACar.java: TestACar.java

class Vehicle {

int numberOfWheels;boolean hasEngine;

Vehicle() { // (1)numberOfWheels = 10;hasEngine = true;run();

Page 158: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 19 ตัวกํากับตวัแปรคลาสและแมธธอส

158

}

void run(){ // (2)numberOfWheels = 4;if (numberOfWheels >= 4) {

System.out.println(“I am running”);}

}

}

class Truck extends Vehicle {

float maximumLoad;

Truck() { // (3)numberOfWheels = 6;hasEngine = true;run();

}

void load(float weight) {if (weight <= maximumLoad)

System.out.println(“I am carrying a “ + weight + “-pound load.”);}

}

public class TestACar {public static void main (String[] args) {

Vehicle myCar = new Vehicle();if (myCar.hasEngine) { // (4)

myCar.run(); // (5)}Truck t = new Truck();

}}

คลาส Vehicle มีตัวแปร numberOfWheels hasEngine และแมธธอส run() ซึ่งสามารถถูกนําไปใชที่ไหนก็ไดภายในคลาส Vehicle เชนในคอนสตรัคเตอรในบรรทัด (1) หรือในตัวแมธธอส run() เองในบรรทัด (2) นอกจากนี้ยังถูกนําไปใชไดภายในคลาส Truck ซ่ึงเปนสับคลาสของ Vehicle เชนในคอนสตรัคเตอรในบรรทัด (3) รวมทั้งถูกนําไปใชไดในคลาส TestACar ซ่ึงไมไดสืบทอดคลาส Vehicle โดยการประกาศอินสแตนทของคลาส Vehicle และเรียกผานอินสแตนทดังในบรรทัด (4) และ (5) กลาวคือสามารถนําไปใชไดทุกท่ีในซอรสไฟล

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

Page 159: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 19 ตัวกํากับตวัแปรคลาสและแมธธอส

159

ๆตองการใชงานตัวแปรคลาสนั้น ๆก็ใหเขียนแมธธอสขึ้นมาไวสําหรับตั้งคาโดยเฉพาะ เราสามารถปรับปรุงโปรแกรมขางตนของเราใหเปนโปรแกรมที่ดีตามหลักของการเขียนโปรแกรมเชิงวัตถุไดดังตัวอยางขางลางนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 19 19 19 19 ---- 2 2 2 2 : TestACar.java: TestACar.java: TestACar.java: TestACar.java

class Vehicle {

private int numberOfWheels; // (1)private boolean hasEngine; // (2)

Vehicle() { // (3)numberOfWheels = 10;hasEngine = true;run();

}

void setNumberOfWheels(int i) { // (4)numberOfWheels = i;

}

void setHasEngine(boolean b) { // (5)hasEngine = b;

}

int getNumberOfWheels() { // (6)return numberOfWheels;

}

boolean getHasEngine() { // (7)return hasEngine;

}

private boolean isReady() { // (8)return (numberOfWheels = 4 && hasEngine)

}

void run(){ // (9)numberOfWheels = 4;if (isReady()) {

System.out.println(“I am running”);}

}

}

class Truck extends Vehicle {

float maximumLoad;

Truck() { // (10)setNumberOfWheels(6);

Page 160: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 19 ตัวกํากับตวัแปรคลาสและแมธธอส

160

setHasEngine(true);run();

}

void load(float weight) {if (weight <= maximumLoad)System.out.println(“I am carrying a “ + weight + “-pound

load.”);}

}

public class TestACar {public static void main (String[] args) {

Vehicle myCar = new Vehicle();if (myCar.getHasEngine()) { // (11)myCar.run(); }Truck t = new Truck();

}}

ในบรรทัด (1) และ (2) ตัวแปรคลาส numberOfWheels และ hasEngine ถูกกําหนดใหเปนตัวแปร private ตัวแปรทั้งสองยังคงถูกนําไปใชไดภายในคลาส Vehicle ดังในบรรทัด (3) และ (9) แตถาตองการอางถึงตัวแปรเหลาน้ีนอกคลาส Vehicle ตองอางถึงโดยการผานแมธธอสในบรรทัด (4) (5) (6)

และ (7)

ตวอยางเชนคอนสตรัคเตอรในบรรทัด (10) ตองเซตคาตัวแปรคลาสจึงใชแมธธอส setNumberOfWheels()และ setHasEngine() โดยสงผานคาคงตัวที่ตองการเขาไป

ในบรรทัด (11) แมธธอส main() ตองการรูคาของตัวแปร hasEngine จึงใชแมธธอส getHasEngine()ซึ่งสงคาของตัวแปร hasEngine ออกมาแทนที่จะเขาถึงตัวแปร hasEngine โดยตรง

การตั้งชื่อแมธธอสสําหรับการเขาถึงตัวแปร private นี้นิยมใชคําวา set และ get ตามดวยชื่อของตัวแปรนั้น ๆในกรณีท่ีตองการเซตคาและทราบคาตามลําดับ ทั้งนี้เปนเพียงความนิยมเทานั้น ไมจําเปนตองตั้งชื่อแบบนี้เสมอไป

ในกรณีของแมธธอส เราสามารถกําหนดใหเปน private ไดดวย การเขียนโปรแกรมเชิงวัตถุที่ดีจะกําหนดใหแมธธอสใดที่มีประโยชนเฉพาะในคลาสเปน private เสมอ ตัวอยางเชนในบรรทัด (8) isReady() เปนแมธธอสที่เขียนขึ้นใชเฉพาะสําหรับการเช็คความเรียบรอยของรถยนตกอนออกวิ่ง ดังนั้นจึงมีที่ใชเฉพาะในแมธธอส run() ในบรรทัด (9) เทาน้ัน เราจึงกําหนดคาแมธธอส isReady() เปน private ในขณะที่ตัวแมธธอส run() เอง มีประโยขนนอกคลาส Vehicle จึงไมกําหนดใหเปน private

Page 161: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 19 ตัวกํากับตวัแปรคลาสและแมธธอส

161

การที่ตัวแปรคลาสและแมธธอสถูกกําจัดใหใชงานไดเฉพาะแตในคลาสดวยการกําหนดใหเปน private น้ีอยาสับสนกับการโอเวอรรายด สับคลาสของซูปเปอรคลาสยังคงสามารถโอเวอรตัวแปรและแมธธอสของซูปเปอรคลาสไดเสมอไมวาตัวแปรและแมธธอสเหลานั้นจะถูกกําหนดใหเปน private หรือไม

อยางไรก็ตามการกําหนดตัวแปรคลาสใหเปน private ก็มีความเสี่ยงอยูเหมือนกัน เพราะถาเราตองการสรางสับคลาสของคลาสน้ันในอนาคต และสับคลาสน้ันตองมีการใชตัวแปรคลาสท่ีเปน private ที่สืบทอดมา จะมีปญหาเพราะตัวแปรคลาส private ไมสามารถถูกกลาวถึงไดเลยในสับคลาส เราตองกลับไปแกไขซูปเปอรคลาสอีก ซ่ึงเปนเร่ืองไมนาพึงประสงคสําหรับการเขียนโปรแกรมท่ีดี

จําไววาสับคลาสจะสืบทอดตัวแปรคลาสและแมธธอสทั้งหมดของซูปเปอรคลาสยกเวนตัวแปรคลาสและแมธธอสที่ประกาศใหเปน private

คําส่ัง publicเราไดเรียนรูมาแลววาเราสามารถกําหนดใหตัวแปรคลาสและแมธธอสถูกอางถึงไดเฉพาะในคลาสเทาน้ันดวยการใชคําส่ัง private

แตถาเราไมกําหนดอะไรเลย ตัวแปรคลาสและแมธธอสจะถูกอางถึงไดทั้งในคลาส และนอกคลาส แตตองเปนคลาสท่ีอยูในแพจเกจเดียวกันเทานั้น ถาตองการใหตัวแปรคลาสและแมธธอสถูกอางถึงนอกแพจเกจไดดวย เราตองใชคําสั่ง public

ท้ังน้ีคลาสน้ันตองเปน public ดวยมิฉะนั้นคําสั่ง public สําหรับตัวแปรคลาสและแมธธอสก็ไมมีประโยชนอะไร

แมธธอส main() เปนแมธธอสหนึ่งที่ตองระบุใหเปน public เสมอ

คําส่ัง protectedคําส่ัง protected เปนคําส่ังท่ีอยูตรงกลางระหวางการไมระบุอะไรเลยใหตัวแปรคลาสและแมธธอส กับการะบุใหเปน public ตัวแปรคลาสและแมธธอสที่ถูกระบุใหเปน protected จะถูกอางถึงไดทั้งในคลาส นอกคลาสในแพจเกจเดียวกัน รวมท้ังสับคลาสของคลาสน้ัน ๆนอกแพจเกจ คลาสท่ีไมใชสับคลาสและอยูนอกแพจเกจเดียวกันเทานั้นที่อางถึงไมได

ท้ังน้ีคลาสน้ันตองเปน public ดวยมิฉะนั้นคําสั่ง protected สําหรับตัวแปรคลาสและแมธธอสก็ไมมีประโยชนอะไร

เคล็ดลับ ตามหลักการเขียนโปรแกรมเชิงวัตถที่เขมงวด ตัวแปรคลาสควรประกาศเปน private คลาสใดที่จะอางถึงหรือ

Page 162: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 19 ตัวกํากับตวัแปรคลาสและแมธธอส

162

เปลี่ยนคาของตัวแปรคลาสตองเขาถึงผานแมธธอสที่สรางไวใหโดยเฉพาะ แตถาคลาสนั้นมีแนวโนมที่จะถูกสืบทอดในอนาคต ใหกําหนดเปน protected แทน เพราะสับคลาสมักตองอางถึงตัวแปรคลาสของซูปเปอรคลาส

Page 163: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

20 คลาส Object

ท่ีจริงแลวคลาสทุกคลาสในภาษาจาวาท้ังท่ีเราสรางข้ึนเอง และทั้งที่มีมาให ตางสืบทอดคลาสคลาสหน่ึงท่ีมีช่ือวา Object เสมอ

การสืบทอดนี้เกิดขึ้นโดยจาวาเปนผูจัดการใหโดยเราไมตองใชคําสั่ง extends แตประการใด ดังน้ันแมวาคลาสทุกคลาสจะสืบทอดคลาส Object ไปแลว คลาสทุกคลาสยังคงสามารถสืบทอดคลาสอ่ืนไดอีกแตไมเกินหน่ึงคลาสเสมอ

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

getClass()

แมธธอส getClass() สงคากลับเปนช่ือคลาสของอินสแตนทน้ัน ๆ ลองดูตัวอยางขางลางน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 20 20 20 20 ---- 1 1 1 1 : TestObject.java: TestObject.java: TestObject.java: TestObject.java

import car.Vehicle;import car.type.Truck;

Page 164: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 20 คลาส Object

164

public class TestObject {public static void main (String[] args) {

Vehicle v = new Vehicle();System.out.println(v.getClass());Vehicle t = new Truck();System.out.println(t.getClass());

}}

ผลการรันโปรแกรมขางตนเปนดังน้ี

แมธธอส getClass() เมื่อใหแสดงออกหนาจอจะไดผลลัพธเปนคําวา class ตามดวยชื่อของคลาสของอินสแตนทนั้น ๆ โปรดสังเกตวาในกรณีของตัวแปรอางอิง t ซึ่งถึงแมวาจะเปนตัวแปรอางอิงชนิด Vehicle แตเน่ืองจากมันถูกกําหนดใหชี้อินสแตนทของคลาส Truck ดังน้ันผลท่ีไดคือคําวา class Truck น้ันคือ แมธธอส getClass() จะแสดงชื่อคลาสโดยดูจากอินสแตนทไมใชจากตัวแปรอางอิงเปนสําคัญ

equals(Object obj)

แมธธอส equals() รับตัวแปรชนิด Object เขาไป แลวสงตัวแปร boolean ออกมา ตัวแปร Object จะเปนตัวแปรอางอิงชนิดใดและช้ีอินสแตนทของคลาสใดก็ได เพราะคลาสทกุคลาสสืบทอดคลาส Object สวนคาของตัวแปร boolean ที่สงออกมา จะเปนจริงก็ตอเมื่ออินสแตนทที่เรียกแมธธอสนี้ กับอินสแตนทตัวที่ถูกสงผานเขาไปในแมธธอสนี้เปนอินสแตนทเดียวกัน ลองดูตัวอยางตอไปน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 20 20 20 20 ---- 2 2 2 2 : TestObject.java: TestObject.java: TestObject.java: TestObject.java

import car.Vehicle;import car.type.Truck;

public class TestObject {public static void main (String[] args) {

Vehicle v1 = new Vehicle();Vehicle v2 = v1;boolean b = v2.equals(v1); // (1)System.out.println(b);

C:\java> javac TestObjectclass Vehicleclass Truck

Page 165: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 20 คลาส Object

165

}}

ผลการรันโปรแกรมขางตนเปนดังน้ี

ตัวแปรอางอิง v1 และ v2 ชี้ไปที่อินสแตนทเดียวกัน ดังน้ันผลลัพธของวลี v2.equals(v1) จึงมีคาเปนจริง ทํานองเดียวกันถาเราใชวลี v1.equals(v2) ก็ยอมไดผลเหมือนกันดวย

จะเห็นไดวาแมธธอส equals() จะใหผลเหมือนกับเครื่องหมาย == ในกรณีของตัวแปรอางอิง เราอาจเปล่ียนคําส่ังในบรรทัด (1) ในตัวอยางขางตนเปนดังนี้แทนก็ได

boolean b = v2 == v1;

เคร่ืองหมาย instanceofภาษาจาวามีเครื่องหมายตัวหนึ่งคือ instanceof (สังเกตวาเขียนดวยตัวพิมพเล็กทั้งหมด) มีไวสําหรับทดสอบวาอินสแตนทหน่ึง ๆเปนอินสแตนทของคลาสหรือสับคลาสของคลาสหน่ึง ๆหรือไม เรานิยมใชเครื่องหมาย instanceof ในการตรวจสอบเพ่ือปองกันความผิดพลาดท่ีอาจเกิดข้ึนเวลารันโปรแกรมเน่ืองจากอินสแตนทกับตัวแปรอางอิงเขากันไมได ลองพิจารณาตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 20 20 20 20 ---- 3 3 3 3 : TestACar.java: TestACar.java: TestACar.java: TestACar.java

class Vehicle {

}

class Truck extends Vehicle {

}

class PrivateCar extends Vehicle {

}

public class TestACar {public static void main(String[] args) {

C:\java> javac TestObjecttrue

Page 166: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 20 คลาส Object

166

PrivateCar p = new PrivateCar();boolean b1 = p instanceof PrivateCar; // (1)System.out.println(“b1 is “ + b1);boolean b2 = p instanceof Vehicle; // (2)System.out.println(“b2 is “ + b2);Vehicle v = p; // (3)boolean b3 = v instanceof PrivateCar; // (4)System.out.println(“b3 is “ + b3);PrivateCar p1 = v; // (5)v = new Vehicle();boolean b4 = v instanceof PrivateCar; // (6)System.out.println(“b4 is “ + b4);if (v instanceof PrivateCar) { // (7)

PrivateCar p2 = (PrivateCar) v;}

}}

ตัวอยางของการใชงานเครื่องหมาย instanceof เปนดังในบรรทัด (1) ดานซายของเครื่องหมายตองเปน ตัวแปรอางอิง สวนดานขวาตองเปนช่ือคลาส ผลลัพธของวลีคือคาความจริง ซึ่งจะจริงก็ตอเมื่อ อินสแตนทท่ี p ชี้อยูสามารถใชกําหนดคาใหตัวแปรอางอิงชนิด PrivateCar ได เน่ืองจากเราสรางตัวแปร p โดยกําหนดใหชี้อินสแตนทของคลาส PrivateCar คาความจริงของ b1 จึงเปน true

ในบรรทัด (2) คาของ b2 ก็ยังคงเปน true เนื่องจากถึงแมวา p จะไมใชอินสแตนทของ Vehicle แต PrivateCar เปนสับคลาสของคลาส Vehicle ดังนั้นตัวแปรอางอิงชนิด Vehicle ยอมสามารถใชชี้อินสแตนทของคลาส PrivateCar ได ดังในบรรทัด (3) ดังน้ัน b2 ยังคงมีคาเปน true

ในบรรทัด (4) แมวา v จะเปนตัวแปรอางอิงแบบ Vehicle แตมันกําลังชี้อินสแตนทของคลาส PrivateCarอยู ดังน้ัน b3 ก็จะมีคาเปน true ดวย เพราะส่ิงท่ี instanceof ตรวจสอบคืออินสแตนทไมใชชนิดของตัวแปรอางอิง และจะตรวจสอบเมื่อรันโปรแกรมแลวเทานั้น ไมมีการตรวจสอบตอนคอมไพล ดังจะเห็นไดจากในบรรทัด (5) เราสามารถกําหนดคาให p ดวย v ได ตรงกันขามถาตัวแปร v ชี้อินสแตนทของ Vehicle คาความจริงจะกลายเปน false ดังในบรรทัด (6)

เพ่ือไมใหโปรแกรมของเราหยุดกระทันหนัเวลารัน เรามักใชเครื่องหมาย instanceof ในการตรวจสอบกอนวาตัวแปรอางอิงที่จะกําหนดคาใหสามารถรับคาที่เรากําหนดคาใหไดจริงหรือไม ดังในบรรทัด (7) บางทีเราไมแนใจวาโปรแกรมที่เรารันมาตั้งแตตนจะทําใหคาของ v เปนอะไรกันแน แมวาเราจะแคสใหมันเปน PrivateCarโปรแกรมจะคอมไพลผานแตเวลารันอาจไมผานก็ไดเราจึงใชเครื่องหมาย instanceof ซึ่งจะตรวจสอบคาของ vตอนรันจริง ๆ

Page 167: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 20 คลาส Object

167

เก่ียวกับการโอเวอรรายดแมธธอสมีขอบังคับอยางหนึ่งในการโอเวอรรายดแมธธอสเกี่ยวกับระดับของการเขาถึงแมธธอส แมธธอสใหมในสับคลาสที่โอเวอรรายดแมธธอสในซูปเปอรคลาส ตองมีการเขาถึงท่ีเทากับหรือผอนปรนมากกวาเดิม ตัวอยางเชน ถาแมธธอสในซูปเปอรคลาสเปน protected แมธธอสในสับคลาสตองเปน protected หรือ public เทาน้ัน จะเปน private หรือไมมีการกําหนดการเขาถึงไมได

finalize()

อินสแตนทของคลาสใดก็ตามที่หมดประโยชนแลวอาจถูกกําจัดไดเสมอโดยจาวาเวอรชัวนแมทชีน เพ่ือเปนการคืนเนื้อที่ของแรมใหแกระบบ แมธธอสนี้เปนแมธธอสที่จะถูกเรียกทุกครั้งกอนที่จาวาเวอรชัวนแมทชีนจะกําจัดอินสแตนทหนึ่ง ๆในแรม อินสแตนททุก ๆอินสแตนทที่เราสรางขึ้นไมวาจะเปนของคลาสใดจะมีแมธธอสนี้อยูเพราะคลาสทกุคลาสสืบทอดคลาส Objectดังน้ันเราสามารถโอเวอรรายดแมธธอส finalize() โดยการใสคําส่ังอะไรลงไปในน้ีก็ได เพื่อใหจาวาเวอรชัวนแมทชีนรันคําส่ังเหลาน้ันเสมอกอนท่ีจะกําจัดอินสแตนท ตวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 20 20 20 20 ---- 4 4 4 4 : TestObject.java: TestObject.java: TestObject.java: TestObject.java

public class TestObject {public static void main (String[] args) {

System.out.println(“main started.”);new TestObject();

}

protected void finalize() {System.out.println(“I am going to die.”);

}}

ในโปรแกรมนี้อินสแตนทของคลาส TestObject() จะถูกสรางขึ้น ถาจาวาเวอรชัวนแมทชีนจะกําจัดอินสแตนทนี้เมื่อใดมันจะพิมพขอความ I am going to die. ออกมากอน

แมธธอส finalize() ตองกําหนดใหเปน protected หรือ public เพราะแมธธอสนี้นิยามไวเปน protected ในคลาส Object เวลาโอเวอรรายดตองใหแมธธอสใหมมกีารเขาถึงเทียบเทาหรือผอนปรนกวาเดิม

Page 168: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 20 คลาส Object

168

อยางไรก็ตามถารันโปรแกรมนี้คุณอาจไมเจอคําวา I am going to die. จนจบโปรแกรม เพราะการจะกําจัดอินสแตนทที่ไมใชแลวหรือไมนั้นขึ้นอยูกับจาวาเวอรชัวนแมทชีน อินสแตนทที่เราไมเรียกใชอีกตอไปไมไดหมายคําวาจะตองถูกกําจัดทันทีโดยจาวาเวอรชัวนแมทชีน

เคล็ดลับ เรานิยมโอเวอรรายดแมธธอส finalize() ในคลาสท่ีมีการเรียกใชงานไฟลหรือเน็ตเวิรก โดยเราจะเขียนคําสั่งบังคับใหคืนทรัพยากรไฟลหรือเน็ตเวิรกแกระบบกอนตัวอินสแตนทเองจะถูกทําลาย เพราะบางครั้งถาไฟลมีปญหาหรือเน็ตเวิรกทํางานชา มักเกิดปญหาที่โปรแกรมจะไมยอมคืนทรัพยากรเหลานั้นใหระบบ คุณจะไดโอเวอรรายดแมธธอสน้ีอีกแน ๆในอนาคตถาคุณตองศึกษาเก่ียวกับการเขาถึงไฟลหรือเน็ตเวิรก

Page 169: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

21 อินเตอรเฟส

ขอจํากัดอยางหน่ึงของการสืบทอดคลาสก็คือ คลาสหน่ึง ๆจะมีซูปเปอรคลาสไดเพียงซูปเปอรคลาสเดียว ในบางกรณีเราตองการสืบทอดคุณลักษณะของคลาสมากกวาหน่ึงคลาส เชน คลาสรถเกงนอกจากจะสืบทอดคุณลักษณะจากคลาสรถยนตแลว บางทีก็อยากสืบทอดคุณลักษณะจากคลาสสินคาดวย เพราะรถเกงเปนท้ังรถยนตและเปนท้ังสินคาไดดวย ดวยเหตุนี้จึงมีสิ่งที่เรียกวา อินเตอรเฟส ซ่ึงก็คือคลาสท่ีคลาสท่ีคลาสอ่ืนสามารถสืบทอดลักษณะไดอีกท้ังท่ีสืบทอดคลาสอ่ืนหรืออินเตอรเฟสอ่ืนไปแลว ลองดูตัวอยางอินเตอรเฟสแบบงาย ๆอินเตอรเฟสหน่ึงดังตอไปน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 21 21 21 21 ---- 1 1 1 1 : MyInterface.java: MyInterface.java: MyInterface.java: MyInterface.java

interface Merchandise {boolean isSaleable = true; // (1)//float price; // (2)void discount(); // (3)

}

เราใชคําส่ัง interface แทนที่จะเปนคําวา class ในการประกาศอินเตอรเฟส จากนั้นก็ตามดวยชื่อของอินเตอรเฟส ซึ่งมีกฏในการตั้งชื่อแบบเดียวกันคลาส ขอสังเกตก็คือวาชื่อไฟลซอรสโคดไมจําเปนตองมีชื่อเหมือนอินเตอรเฟส และไมจําเปนตองมีอินเตอรเฟสที่มีคําวา public อยูอยางนอยหน่ึงอินเตอรเฟสในไฟล เพราะอินเตอรเฟสถือวาเปน public อยูแลวโดยไมตองมีการประกาศ

Page 170: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 21 อินเตอรเฟส

170

ถาอินเตอรเฟสไมมีขอจํากัดในการสืบทอดอยางในกรณีของคลาส ทุกคงก็คงใชแตอินเตอรเฟส ไมมีใครใชคลาสอีกตอไป แตในความเปนจริงไมเปนเชนนั้น เพราะอินเตอรเฟสมีขอจํากัดอยางอื่นอีกมากมายที่ไมมีในคลาส ขอกําจัดที่เห็นไดชัดท่ีสุดก็คือ ตัวแปรของอินเตอรเฟสตองตองมีคาแนนอนเสมอและตองกําหนดคาไวในนิยามของอินเตอรเฟส ในขณะที่แมธธอสของอินเตอรเฟสตองมีแตชื่อไมมีตัวหรือไปไดไดแคแมธธอสนามธรรมนั่นเอง

ในบรรทัด (1) เรานิยามตัวแปร isSaleable ไวบอกความเปนสินคา ซึ่งกําหนดคาไวแลววาเปน true คาของตัวแปรอินเตอรเฟสตองกําหนดไวในอินเตอรเฟสเสมอและจะเปล่ียนแปลงภายหลังไมได พูดงาย ๆก็คือ เปนตัวแปรถาวรเสมอโดยไมตองมกีารระบุ ดังนั้นตัวแปร price ในบรรทัด (2) จึงไมอาจประกาศไดเพราะไมมีคา

ในบรรทัด (3) แมธธอส discount() มีแตชื่อไมมีตัว เพราะแมธธอสในอินเตอรเฟสเปนแมธธอสนามธรรมเสมอโดยไมตองมีการระบุ ดังน้ันก็ไมตองสงสัยเลยวา ตัวอินเตอรเฟสยอมเปนคลาสนามธรรมไปดวย เราไมสามารถสรางอินสแตนทของอินเตอรเฟสได

เวลาคลาสจะสืบทอดอินเตอรเฟส เราใชคําส่ัง implements แทนที่จะเปน extends ดังตัวอยางขางลาง

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 21 21 21 21 ---- 2 2 2 2 : PrivateCar.java: PrivateCar.java: PrivateCar.java: PrivateCar.java

import car.Vehicle;

interface Merchandise {boolean isSaleable = true;void discount();

}

public class PrivateCar extends Vehicleimplements Merchandise { // (1)

int numberOfPassengers;

void playCD() {System.out.println(“CD is playing.”);

}

public void discount() { // (2)if (isSaleable) {

System.out.println(“Price reduced.”);}

}}

ในบรรทัด (1) คลาส PrivateCar สืบทอดท้ังคลาส Vehicle และอินเตอรเฟส Merchandise ถาคลาสตองการสืบทอดอินเตอรเฟสมากกวาหน่ึงอินเตอรเฟสก็ทําไดโดยใชเครื่องหมายจุลภาคคั้น ตัวอยางเชน

class classA implements interfaceB, interfaceC {

Page 171: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 21 อินเตอรเฟส

171

}

อินเตอรเฟสสามารถสืบทอดอินเตอรเฟสไดดวย แตในกรณีนี้เราจะใชคําสั่ง extends แทน ตัวอยางเชน

interface A { /* ... */ }interface B { /* ... */ }interface C extends A,B { /* ... */ }

ในขณะท่ีคลาสสืบทอดอินเตอรเฟสได อินเตอรเฟสกลับไมสามารถสืบทอดคลาสได ตวอยางตอไปนี้ผิดclass A { /* ... */ }interface B extends A { /* ... */ } // Error

แมธธอส discount() ในบรรทัด (2) เปนการนําเอาแมธธอสนามธรรมท่ีประกาศไวในอินเตอรเฟสมานิยาม ซ่ึงจะละไมไดเพราะคลาสที่สืบทอดอินเตอรเฟสตองนิยามแมธธอสทุกแมธธอสท่ีอินเตอรเฟสประกาศไวมิฉะน้ันตวคลาสเองจะตองประกาศเปนคลาสนามธรรมซ่ึงจะทําใหนําไปสรางอินสแตนทไมได

ทั้งตัวแปรและแมธธอสในอินเตอรเฟสจะเปน public โดยอัติโนมัติไมตองมีการระบุ สังเกตวาแมธธอส discount() ท่ีอยูในคลาส PrivateCar ตองเปน public ดวย เพราะการโอเวอรรายดแมธธอส แมธธอสตัวใหมตองมีอิสระในการเขาถึงเทากับหรือนอยกวาแมธธอสตนแบบ

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

Page 172: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม
Page 173: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

22 คอลเล็กช่ัน

จาวามีคลาสกลุมหนึ่งที่เรียกวา คอลเล็กช่ัน คลาสกลุมนี้มีไวสําหรับชวยจัดการกับขอมูลจํานวนมาก เชน การเรียงลําดับขอมูล การคนขอมูล การเรียนรูและเขาใจการใชงานคอลเล็กชั่นนอกจากจะชวยใหเขียนโปรแกรมที่ตองมีการจัดการกับขอมูลจํานวนมาก ๆไดแลว คลาสกลุมน้ียังมีการเช่ือมโยงกันดวยอินเตอรเฟส จึงชวยทําใหเราเขาใจเรื่องอินเตอรเฟสไดดีข้ึนอีกดวย

คําวาคอลเล็กชั่นหมายถึงกลุมของขอมูล คอลเล็กช่ันแบงออกเปนหลายประเภทยอย ๆตามวิธีการเก็บขอมูล ในภาษาจาวาคอลเล็กชัน่คลาส คอลเล็กช่ันแตละประเภทนิยามดวยคลาสหน่ึงคลาส คลาสเหลานี้อยูในแพจเกจชื่อ java.util และคลาสท้ังหลายเหลาน้ีจะเช่ือมโยงกันดวยอินเตอรเฟสหลักช่ือวา Collection ดังแผนภาพตอไปน้ี

มีกลุมของขอมูลอีกจําพวกหนึ่งซึ่งใชเก็บขอมูลไดเหมือนกันแตไมจัดเปนคอลเล็กช่ัน เราเรียกวา แม็บ เน่ืองจากเราไมถือวาแม็บเปนคอลเล็กชั่นจึงไมมีการโยงความสัมพันธเขากับอินเตอรเฟส Collection แม็บทุกชนิดจะโยงเขากับอินเตอรเฟส Map แทน

ถึงตอนน้ีเราอาจจะยังมองภาพไมออกวาคอลเล็กชัน่มีหนาตาเปนอยางไร เราจะเขาใจมันไดดียิ่งขึ้นเมื่อเรากลาวถึงตวอยางโปรแกรมที่ใชงานจริง ตอนน้ีอยากใหดูกอนวาอินเตอรเฟส Collection ประกาศแมธธอสอะไรไวบาง

Page 174: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 22 คอลเล็กชัน่

174

อินเตอรเฟส Collection

อินเตอรเฟส Collection มีการประกาศแมธธอสซึ่งบอกความเปนคอลเล็กชั่นไวหลายตัว คอลเล็กช่ันคือกลุมของขอมูล ดงนั้นตองสามารถจัดการขอมูลได ดังนั้นแมธธอสที่ประกาศไวในอินเตอรเฟส Collection จึงหนีไมพนแมธธอสเกี่ยวกับการจัดการขอมูล เชน การเพิ่มการลดขอมูล ตอไปนี้เปนตัวอยางของแมธธอสในอินเตอร Collection ที่ควรรูจัก

boolean add(Object element)

แมธธอส add() รับขอมูล element เขาไปในคอลเล็กช่ัน ขอมูลในคอลเล็กช่ันจะเปนอะไรก็ไดขอใหอยูในเปนวัตถุในภาษาจาวา เมื่อรับขอมูลไปแลวแมธธอส add() จะสงคาตรรกกลับมาดวยวาการเพิ่มขอมูลสําเร็จหรือไม

boolean remove(Object element)

แมธธอส remove() ทํางานในทํานองเดียวกับ add() แตเปนการเอาขอมลูออกจากคอลเล็กชัน่

boolean contains(Object element)

แมธธอส contains() ทําการตรวจสอบวาคอลเล็กช่ันน้ันมีขอมูล element อยูหรือไม ไมมีการเปล่ียนแปลงแกไขขอมูลใด ๆในคอลเล็กช่ัน โปรดสังเกตวาในขณะที่แมธธอส add() และ remove() จะจัดการกับขอมูลในเซตอยางถาวร แมธธอส contains() จะเพียงแคตรวจสอบเทานั้น ไมมีแตะตองขอมูล

boolean containsAll(Collection c)boolean addAll(Collection c)boolean removeAll(Collection c)

แมธธอสเหลานี้เหมือนกับแมธธอสที่กลาวมาแลวแตแทนที่จะรับขอมูลทีละหนึ่งวัตถุ มันจะรับขอมูลทีละมาก ๆจากคอลเล็กช่ันอ่ืนเลย

retainAll(Collection c)

แมธธอสนี้คงคาในคอลเล็กชั่นเฉพาะคาที่อยูใน c ดวยเทานั้น นอกน้ันจะเอาออกหมด

void clear()

แมธธอสนี้ลางขอมูลที่คางอยูในคอลเล็กชั่นออกหมด

boolean isEmpty()

แมธธอส isEmpty() ตรวจสอบวาคอลเล็กชั่นมีขอมูลอยูบางหรือไม

int size() แมธธอส size() คืนคาจํานวนสมาชิกของคอลเล็กช่ัน

Object[] toArray(Object a[]);

แมธธอส toArray() ใชเปล่ียนคอลเล็กช่ันใหกลายเปนอะเรย ตัวแปรสงผาน a[] เปนการบอกใหรูวาอะเรยตัวที่จะมารับคาไปเปนอะเรยชนิดใดมีขนาดเทาใด ถามีขนาดเล็กกวาคอลเล็กช่ัน จะมีการตัดสวนเกินท้ิงกอน

Page 175: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 22 คอลเล็กชัน่

175

แมธธอสในอินเตอรเฟสเปนแมธธอสนามธรรม ดังน้ันคลาสใด ๆก็ตามที่สืบทอดอินเตอรเฟสนี้จะตองนิยามแมธธอสเหลาน้ี ดังนั้นคอลเล็กชั่นทุกชนิดจะมีแมธธอสชื่อเดียวกันนี้อยู

เซตคอลเล็กช่ันชนิดแรกก็คือ เซต ซึ่งไดแกกลุมของขอมูลที่หามมีสมาชิกที่มีหนาตาเหมือนกันอยู ในภาษาจาวาเซตเปนอินเตอรเฟส เราไมสามารถใชงานอินเตอรเฟสไดโดยตรงเพราะอินเตอรเฟสสรางอินสแตนทไมได คลาสท่ีเราใชทํางานเปนเซตจริง ๆคือ คลาส HashSet และคลาส TreeSet

ขอแตกตางของ HashSet กับ TreeSet ก็คือ คลาส TreeSet จะมีการเรียงขอมูลที่เขาไปใหโดยอัตโนมัติ ลองดูตัวอยางการใชงานคลาสท้ังสองน้ีดู

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 22 22 22 22 ---- 1 1 1 1: TestSet.java: TestSet.java: TestSet.java: TestSet.java

import java.util.*;

public class TestSet {public static void main(String args[]) {

Integer i = new Integer(5); // (1)Integer j = new Integer(1);Integer k = new Integer(6);

HashSet s = new HashSet(); // (2)s.add(i); // (3)s.add(j); // (4)s.add(j); // (5)s.add(k); // (6)System.out.println(s);s.remove(i); // (7)System.out.println(s);

Set t = new TreeSet(); // (8)t.add(i); // (9)t.addAll(s); // (10)System.out.println(t); // (11)

Integer[] integer = t.toArray(new Integer[10]); // (12)

}}

ผลการรันเปนดังน้ี

Page 176: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 22 คอลเล็กชัน่

176

ในบรรทัด (1) เราสรางวัตถุของคลาส Integer ขึ้นมาสามตัวเก็บชื่อ i,j,k เก็บคา 5,6,1 ตามลําดับ

ในบรรทัด (2) เราสรางวัตถุของคลาส HashSet ขึ้นมาชื่อ s เน่ืองจากคลาส HashSet สืบทอดอินเตอรเฟส Collection ดงน้ันยอมใชแมธธอสของอินเตอรเฟส Collection ได

ในบรรทัด (3) (4) (5) (6) เราใสวัตถุ i, j, j, k ลงไปใน s วัตถุใด ๆสามารถใสเขาไปในคอลเล็กชั่นไดทั้งนั้น เพียงแตตองเปนวัตถุของคลาสเดียวกันทุกตัว สังเกตวาเราใส j ซํ้าสองหน เม่ือลองแสดงคาของ sออกนอกจอ จะพบวา s เปนเซตที่มีสมาชิกสามตัวคือ 6,5,1 การใสวัตถุที่มีคาซ้ําลงไปจะไมถูกเก็บเพราะโดยคุณสมบัติของเซต สมาชิกของเซตจะมีคาซ้ํากันไมได นอกจากน้ี สังเกตดูใหดีวาโปรแกรมจะเขียนสมาชิกเรียงลําดับจากตัวสุดทายที่เราใสเขาไปในเซตไปหาตัวแรกสุด

ในบรรทัด (7)เราเอาวัตถุ i ออกจากเซต แลวแสดงผลหนาจอใหม ปรากฏวา สมาชิกเหลือแคสองตัวคือ 6 และ 1

ในบรรทัด (8)สรางเซตใหมเปนแบบ TreeSet ชื่อวา t การประกาศเซตคราวน้ีมีการเลนกลนิดหนอยคือแทนท่ีจะประกาศตัวแปรอางอิงชนิด TreeSet โดยตรง กลับประกาศใหเปนแบบ Set การประกาศแบบน้ีทําไดเสมอ เพราะ Set เปนซูปเปอรคลาสของ TreeSet ตัวแปรอางอิงชนิด Set ยอมใชชี้อินสแตนทของคลาส TreeSetไดเสมอ

ในบรรทัด (7) เราใสวัตถุ i ลงไปใน t จากน้ันก็ใสเซต s ตามลงไปอีกทั้งเซต ผลท่ีไดคือ 6 5 1 เหมือนเดิม เพราะวัตถุ i มีคาเทากับ 5 สวนเซต s มีคาเทากับ [6,1] แตคราวน้ีเวลาแสดงผลออกนอกจอ จะเรียงลําดับจากมากไปนอย คือ [1,6,5] แทน เพราะ TreeSet จะมีการเรียงลําดับใหในเซตโดยอัตโนมัติ โดยไมสนใจวาสมาชิกตัวไหนถูกใสลงไปกอนหรือหลัง

ในบรรทัด (12) เปนตัวอยางการโอนขอมลูในเซตไปใสอะเรย

boolean containsAll(Collection c)

ในอินเตอรเฟสเซตมีการนิยามแมธธอสชื่อ containsAll แมธธอสนี้จะคืนคาจริงหากเซตนั้น ๆมีสมาชิกของ cทุกตัวอยูภายใน

C:\java> javac TestSet[6, 5, 1][6, 1][1, 5, 6]

Page 177: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 22 คอลเล็กชัน่

177

ลิสตลิสตเปนคอลเล็กช่ันอีกชนิดหน่ึง แตแตกตางกับ เซต ตรงที่มีสมาชิกซ้ํา ๆกันได และสมาชิกของลิสตจะมีลําดับประจําตัวของมันอยู ลิสตในภาษาจาวาเปนอินเตอรเฟสช่ือ List ซ่ึงสืบทอดมาจากอินเตอรเฟส Collectionอีกที แมธธอสที่ประกาศไวในอินเตอรเฟส List มีดังตอไปนี้

void add(int index, Object element)

แมธธอส add() รับวัตถุเขาไปเก็บไวในลิสต โดยจะถูกเก็บไวเปนลําดับที่ index

boolean addAll(int index, Collection c)

แมธธอส addAll() รับวัตถุเขาไปทีละมาก ๆในรูปของคอลเล็คช่ัน

Object remove(int index)

แมธธอส remove() ลบขอมูลในลําดับท่ี index ออกจากลิสต

Object get(int index)

แมธธอส get() คืนคาขอมูลในตําแหนง index

Object set(int index, Object element)

แมธธอส set() เปลี่ยนคาของขอมูลในตําแหนง index ใหเทากับวัตถุที่รับเขาไป

int indexOf(Object o)

คืนคาตําแหนงที่วัตถุ o อยูในลิสต ถาไมพบจะคืนคา –1 มันจะหยุดคนทันทีที่เจอวัตถุ o เปนคร้ังแรก

int lastIndexOf(Object o)

คืนคาแบบเดียวกับ indexOf() แตเริ่มคนจากทาย

คลาสท่ีเราใชงานเปนลิสตจริง ๆคือ ArrayList, Vector และ LinkedList คลาสท้ังสามสืบทอดอินเตอรเฟส List คลาสท้ังสามน้ีคลายกันมาก แตตัวที่นิยมใชมากที่สุดคือ ArrayList เราใช Vector ก็ตอเมือ่เราตองมีการระวังขอมูลสับสนเมื่อมีคนเขาถึงขอมูลพรอม ๆกันทีละหลาย ๆคน และเราใช LinkedList เมื่อขอมูลของเรามีการลบและแทรกบอย ๆ นอกน้ันเราใช ArrayList เพราะทํางานไมซับซอนและตอนสนองรวดเร็ว

ตัวอยางการใชงานลิสตเปนดังนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 22 22 22 22 ---- 2 2 2 2 : TestList.java: TestList.java: TestList.java: TestList.java

import java.util.*;

public class TestList {public static void main(String args[]) {

Character c = new Character(‘a’); // (1)Character d = new Character(‘b’);Character e = new Character(‘c’);

Set s = new HashSet();// (2)

Page 178: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 22 คอลเล็กชัน่

178

List a = new ArrayList();s.add(c); // (3)a.add(c);s.add(d); // (4)a.add(d);s.add(e); // (5)a.add(1,e); // (6)System.out.println(s);System.out.println(a);a.addAll(3,s); // (7)System.out.println(a);

}}

ผลการรันเปนดังน้ี

ในบรรทัด (1) เราสรางวัตถุของคลาส Character ขึ้นมาสามตัวชื่อ c,d,e แตใชเก็บอักษร a,b,c ตามลําดับ

ในบรรทัด (2) และบรรทัดตอมาเราสรางเซตขึ้นมาหนึ่งเซตชื่อ s และลิสตหน่ึงลิสตช่ือ a

ในบรรทัด (3) และบรรทัดตอมาเราใสอักษร a ใหกับทั้ง s และ a อยาลืมวาคลาส ArrayList แมจะสืบทอดมาจากอินเตอรเฟส List แตอินเตอรเฟส List สืบทอดอินเตอรเฟส Collection มาอีกที ดังนั้นตองมีแมธธอส add() แบบไมม ีindex พวงมาดวยเหมือนกัน

ในบรรทัด (4) และบรรทัดตอมาเราใสอักษร b ใหทั้ง s และ aในบรรทัด (5) และบรรทัด (6) เราใสอักษร c ใหทั้ง s และ a แตคราวนี้เราใช index เพ่ือเลือกท่ีแทรกดวยในกรณีของ a และเน่ืองจากดรรชนีเร่ิมจาก 0 ดงน้ัน ตําแหนง 1 หมายถึงตัวที่สอง ผลท่ีไดก็คือพอแสดงคา s และ a ออกหนาจอ c ของ a จะอยูในตําแหนงที่สองแทนที่จะเปนตําแหนงสุดทายอยางในกรณีของเซต เพราะ ลิสตมีลําดับประจําตัว

ในบรรทัด (7) เราใสสมาชกิท้ังหมดของเซต s เขาไปใน a ท่ีเราใสเซตเขาไปในลิสตไดท้ังท่ีเปนคอลเล็กช่ันคนละประเภทเปนเพราะเซตกับลิสตถูกโยงใหสัมพันธกันดวยอินเตอรเฟสคอลเล็กชัน่ แมธธอส addAll(int index,

C:\java> javac TestList[b, a, c][a, c, b][a, c, b, b, a, c]

Page 179: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 22 คอลเล็กชัน่

179

Collection c) รับวัตถุอะไรก็ไดท่ีเปน Collection ดังน้ันเซตจึงเขาไปไดดวยเพราะเซตจัดวาเปนคอลเล็กชั่นดวย ตัวอยางนี้แสดงใหเห็นประโยชนของอินเตอรเฟส

เม่ือแสดง a ออกหนาจออีกคร้ังจะได a ซึ่งมีสมาชิกของ s ทั้งหมดแทรกเขามาในตําแหนง 3 สังเกตวาลิสตไมเหมือนกับเซตเพราะถาขอมูลซํ้ามันจะถือวาเปนคนละตัวกัน

บางคร้ังเราตองการจัดการขอมูลในลิสตทุกตัวทีละตัว จาวาสรางอินเตอรเฟสหนึ่งขึ้นมาไวชวยในการเขาถึงลิสตแบบเรียงตัวโดยเฉพาะชื่อวา ListIterator อินเตอรเฟสน้ีเปนเสมือนดรรชนีท่ีว่ิงไปตามลําดับของขอมูลในลิสตจากตัวแรกจนถึงตัวสุดทาย มีแมธธอสที่นาสนใจดังนี้

ListIterator listIterator()

แมธธอสนี้มีไวผูก ListIterator เขากับลิสตหน่ึง เพื่อเตรียมการณเขาถึงแบบเรียงตัว

boolean hasNext()boolean hasPrevious()

แมธธอส hasNext()คืนคาจริง ถายังมีขอมูลเหลืออยูในลิสตอีกที่ยังไมไดจัดการ แมธธอส hasPrevious()คืนคาจริงถามีขอมูลอยูกอนหนาขอมูลตัวที่กําลังสนใจอยู

Object next()Object previous()

แมธธอส next() คืนคาเปนตัวขอมูลที่อยูในตําแหนงหลังตําแหนงปจจุบันของดรรชนี ListIterator สวน previous() คืนคาเปนตัวขอมูลที่อยูขางหนา

ตัวอยางการใชงาน ListIterator เปนดังน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 22 22 22 22 ---- 3 3 3 3 : TestListIterator.java: TestListIterator.java: TestListIterator.java: TestListIterator.java

import java.util.*;

public class TestListIterator {public static void main(String args[]) {

Character c = new Character(‘a’);Character d = new Character(‘b’);Character e = new Character(‘c’);

List a = new ArrayList();a.add(c);a.add(d);a.add(e);

ListIterator p = a.listIterator(); // (1)while (p.hasNext()) { // (2)

System.out.println(p.next());}

}

Page 180: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 22 คอลเล็กชัน่

180

}

ผลการรันโปรแกรมขางตนเปนดังน้ี

เชนเคยในโปรแกรมนี้เราสรางลิสตขึ้นมาลิสตหนึ่งชื่อ a แลวใสตัวอักษร a,b,c ลงไป

ในบรรทัด (1) เราประกาศตัวแปร p ซึ่งเปนตัวแปรอางอิงชนิด ListIterator แลวกําหนดใหมีคาเทากับ a.listIterator() ไมตองสงสัยเลยวาท่ีจริงแลวคลาสลิสตทุกตัวสืบทอดอินเตอรเฟส ListIteratorดวย

ในบรรทัด (2) เราใชลูป while ในการเขาถึงขอมูลในลิสตแบบเรียงตัว คาของ p.hasNext() คอยบอกวาขอมูลหมดหรือยัง สวน p.Next() สงคาของขอมูลออกมา ซึ่งเมื่อเรียกแมธธอสนี้แลวครั้งหนึ่ง ตําแหนงที่ p ชี้ขอมูลในลิสตจะเลื่อนไปหนึ่งตําแหนงโดยอัติโนมัติ ลูป while จึงวนไปเรื่อย ๆจนกวา p.Next() จะเปนเท็จ ซึ่งหมายถึงเขาถึงขอมูลตัวสุดทายไปแลว โปรแกรมก็จะหลุดออกมาจากลูป ผลท่ีไดคือการเขียนอักษรออกหนาจอทีละตัวท้ังลิสต

ในแพจเกจ java.util มีคลาสคลาสหน่ึงช่ือ Collections (อยาสับสนกับอินเตอรเฟส Collection)ซึ่งมีแมธธอสสแตรติกอยูตัวหนึ่งที่มีประโยชนสําหรับลิสตคือแมธธอส sort()

static void sort(List list)

แมธธอส sort() เรียงลําดับขอมูลในลิสตใหใหม

ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 22 22 22 22 ---- 4 4 4 4 : TestList.java: TestList.java: TestList.java: TestList.java

import java.util.*;

public class TestList {public static void main(String args[]) {

List a = new ArrayList();a.add(new Integer(2));a.add(new Integer(1));a.add(new Integer(3));System.out.println(a);Collections.sort(a);

C:\java> javac TestListIteratorabc

Page 181: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 22 คอลเล็กชัน่

181

System.out.println(a);

}}

ผลการรันเปนดังน้ี

แม็บแม็บ คือ กลุมของขอมูลที่มีการจัดการโดยใชคีย กลาวคือการเขาถึงขอมูลตองผานคียกอนเสมอ ในแม็บหนึ่ง ๆคียจะมีคาซํ้ากันไมได ในขณะที่ตัวขอมูลเองอาจซ้ํากันได แม็บไมจัดเปนคอลเล็กชั่น ในภาษาจาวาแมบ็เปนอินเตอรเฟสชื่อ Map ซึ่งประกาศแมธธอสตอไปนี้ไว

Object put(Object key, Object value)

แมธธอส put() ทําหนาที่รับขอมูลเขาสูแม็บ ซึ่งตองมีการระบุคียที่ใชอางอิงเวลาตองการจะเรียกใชขอมูลอีกในอนาคต

Object get(Object key)

แมธธอส get() ใชเขาถึงขอมูลในแม็บ ซึ่งตองสงผานคียเขาไปมันจึงไปเอาขอมูลที่เราตองการออกมาใหได

Object remove(Object key)

แมธธอส remove() ลบขอมูลออกจากแม็บดวยการระบุคียของขอมูลนั้น

boolean containsKey(Object key)

แมธธอส containsKey() ใชทดสอบเฉย ๆวามีขอมูลที่มีคียเทากับตัวแปร key ที่สงเขาไปหรือไม

boolean containsValue(Object value)

แมธธอส containsValue() ใชทดสอบวามีขอมูลตวนี้อยูในแม็บหรือไม

int size()

คืนคาเทากับจาํนวนสมาชิกในแม็บ

boolean isEmpty()

คือคาจริง หากไมมีขอมูลอยูในแม็บ

void putAll(Map t)

C:\java> java TestList[2, 1, 3][1, 2, 3]

Page 182: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 22 คอลเล็กชัน่

182

ใชสงขอมูลเขาไปในแม็บทีละมาก ๆ ดวยการสงเขาไปในรูปของแม็บตัวอื่น

void clear()

ลบขอมลูออกจากแม็บใหหมด

Set keySet()Collection values()

แมธธอส keySet() คืนคาของคียทุกตัวในแม็บออกมาในรูปของเซต แมธธอส values() คืนคาของขอมูลทุกตัวออกมาในรูปของคอลเล็กชัน่ แตไมใชเซต เพราะขอมูลในแม็บอาจซ้ํากันได

คลาสท่ีสืบทอดอินเตอรเฟส Map มีสามคลาสคือ HashMap ,HashTable และ TreeMap โดยมากเรานิยมใช HashMap เพราะไมซับซอนจึงเร็ว สวน HashTable เรามักใชในกรณีที่อาจมีผูใชมากกวาหนึ่งคนเขาถึงแม็บพรอม ๆกัน และ TreeMap ใชในกรณีที่ตองการเรียงลําดับขอมูลดวย

ลองดูตวอยางการใชงานแม็บดงตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 22 22 22 22 ---- 5 5 5 5 : TestMap.java: TestMap.java: TestMap.java: TestMap.java

import java.util.*;

public class TestMap {public static void main(String args[]) {

Map m = new HashMap();// (1)m.put(new Integer(1), new Character(‘a’));m.put(new Integer(2), new Character(‘b’));m.put(new Integer(3), new Character(‘b’));System.out.println(m);Set s = m.keySet(); // (2)System.out.println(s);

}}

ผลการรันเปนดังน้ี

C:\java> java TestMap{3=b, 2=b, 1=a}[3, 2, 1]

Page 183: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 22 คอลเล็กชัน่

183

อินเตอรเฟส Comparableถาเราตองการเซตท่ีเรียงลําดับเราใช TreeSet ถาเราตองการลิสตท่ีเรียงลําดับเราอาศัย Collections.sort() ในการชวยเรียง และถาเราตองการแม็บที่เรียงลําดับเราใช TreeMap หลักการเรียงลําดับท่ีใชในกรณีน้ีเปน การเรียงลําดับธรรมชาติ ซึ่งหมายถึง ถาวัตถุเปนตัวเลขก็เรียงตามคา ถาวัตถุเปนตัวอักษรก็เรียงตามลําดับในรหัสยูนิโคด ถาวัตถุเปนวันที่ก็เรียงตามเวลา และถาวัตถุเปนขอความก็เรียงลําดับตามลําดับในพจนานุกรม แตถาวัตถุไมไดเปนดังที่กลาวมาเชน วัตถุท่ีเราสรางเอง เราจะเรียงลําดับอยางไร

สมมติวาเราเขียนโปรแกรมจัดการฐานขอมูลลูกคา เราสรางคลาสช่ือ Customer ขึ้นมาแทนตัวลูกคาแตละคนดังนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 22 22 22 22 ---- 6 6 6 6 : Customer.java: Customer.java: Customer.java: Customer.java

class Customer {

String firstname;String lastname;int telephone;

Customer() { }Customer(String firstname,String lastname, int telephone) {

this.firstname = firstname;this.lastname = lastname;this.telephone = telephone;

}}

ถาเราเก็บวัตถุของคลาส Customer ขางตนไวในคอลเล็กช่ันท่ีมีการเรียงลําดับ ปญหาจะเกิดขึ้นเพราะจาวาไมรูวาจะเรียงลําดับดวยหลักการอะไร ชื่อ นามสกุล หรือหมายเลขโทรศัพท เราสามารถกําหนดหลักการเรียงลําดับไดดวยตนเองโดยการใหคลาส Customer ของเราสืบทอดอินเตอรเฟส Comparable ซึ่งมีการประกาศแมธธอสแคหนึ่งตัวดังนี้

int CompareTo(Object o)

แมธธอส CompareTo() ทํางานคลาย ๆกับแมธธอส equals() ในคลาส Object กลาวคือถาวัตถุมีคาเทากับวัตถุ o มันจะคืนคา 0 ถานอยกวามันจะคืนคาติดลบ และถามากกวามันจะคืนคาบวก เราสามารถโอเวอรรายดแมธธอส CompareTo() ไดใหมในคลาส Customer ของเรา ซึ่งจะทําใหจาวาเรียงลําดับวัตถุของเราตามใจเราโดยอัตโนมัติ

ลองดูตัวอยางดังตอไปน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 22222222---- 7: TestSort.java7: TestSort.java7: TestSort.java7: TestSort.java

class Customer implements Comparable { // (1)

Page 184: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 22 คอลเล็กชัน่

184

String firstname;String lastname;int telephone;

Customer() { }Customer(String firstname,String lastname, int telephone) {

this.firstname = firstname;this.lastname = lastname;this.telephone = telephone;

}

public int compareTo(Object o){ // (2)Customer c = (Customer) o; // (3)int i = lastname.compareTo(c.lastname); // (3)return (i != 0 ? i : firstname.compareTo(c.firstname)); //

(4)}

}

public class TestSort {public static void main(String args[]) {

Customer customer1 = new Customer("Adam", "Smith",7127000);

Customer customer2 = new Customer("James", "Dean",7187000);

Customer customer3 = new Customer("Bob", "Dylan",6119000);

Customer customer4 = new Customer("James", "Bond",7120007);

Set s = new TreeSet();s.add(customer1);s.add(customer2);s.add(customer3);s.add(customer4);

Iterator i = s.iterator(); // (5)while (i.hasNext()) {

Customer c = (Customer) i.next();System.out.println(c.firstname+" " +c.lastname+"

"+c.telephone);}

}

ผลการรันโปรแกรมเปนดังน้ี

Page 185: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 22 คอลเล็กชัน่

185

ในบรรทัด (1) เราใหคลาส Customer ของเราสืบทอดอินเตอรเฟส Comparable

ในบรรทัด (2) เรานิยามแมธธอส compareTo() ของเราใหม สังเกตวาเราตองประกาศใหเปนแมธธอสสาธารณะ เพราะแมธธอส compareTo() ประกาศไวในอินเตอรเฟส ซึ่งจะเปนแมธธอสสาธารณะโดยปริยาย ทําใหเราไมสามารถกําหนดการเขาถึงใหออนกวา public ได

ในบรรทัด (4) เราคืนคาเหมือนกับการเรียงลําดับตามช่ือ แตถาชื่อเหมือนกันใหเรียงลําดับตามนามสกุล ซ่ึงเรานิยามไวแลวในบรรทัด (3) สังเกตวาตัวแปรสตริงก็เรียงแมธธอส compareTo() ไดดวย เพราะที่จริงแลวตัวแปรพ้ืนฐานทุกชนิดรวมท้ังตัวแปรสตริงก็สืบทอดอินเตอรเฟส compareTo() อยูแลวเหมือนกัน

ในโปรแกรมหลักของเรา เราสรางวัตถุของคลาส Customer ขึ้นมาสี่ตัว แลวใสลงไปใน TreeSet มันจะเรียงลําดับตามที่เรานิยามไวแลวใน compareTo() โดยอัติโนมัติ

สังเกตในบรรทัด (5) ถาเราตองการเขาถึงเซตแบบเรียงตัว เราสรางตัวช้ีในทํานองเดียวกันกับลิสต แตเราสรางจากอินเตอรเฟส Iterator แทนที่จะเปน ListIterator

C:\java> java TestSortJames Bond 7120007James Dean 7187000Bob Dylan 6119000Adam Smith 7127000

Page 186: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม
Page 187: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

23 เอ็กซเซฟช่ัน

โปรแกรมประยุกตที่ใชงานจริงตองคอยระวังไมใหโปรแกรมหยุดทํางานกระทันหันเนื่องจากมีเหตุอันไมพึงประสงคเกิดข้ึน เหตุอันไมพึงประสงคเหลาน้ันเปนไปไดหลายกรณีมาก ตัวอยางเชน ผูใชใสคําสั่งผิด ผูใชกรอกตัวเลขศูนยเปนตัวหาร โปรแกรมตองการบันทึกขอมูลลงบนดิสกแตดิสกชํารุด โปรแกรมตองการสงขอมูลออกไปยังเน็ตเวิรกแตเน็ตเวิรกตอบสนองชาผิดปกติ เปนตน

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

เอ็กซเซฟชั่นเปนวัตถุในภาษาจาวา เอ็กซเซฟช่ันทุกเอ็กซเซฟช่ันสืบทอดมาจากคลาส Throwable ซึ่งอยูในแพจเกจ java.lang ซึ่งมีมาใหอยูแลวโดยที่เราไมตองสรางหรืออิมพอรตเขามาในโปรแกรมของเรา ภายใตคลาส Throwable มีสองสับคสาสคือ คลาส Error และคลาส Exception

Throwable

Error Exception

RuntimeExceptionInterruptedException IOException

ArithmeticException NullPointerException

Page 188: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 23 เอ็กซเซฟชั่น

188

คลาส Error จัดการเอ็กซเซฟชั่นที่เกิดขึ้นกับตัวจาวาเวอรชัวนแมทชีนเอง เอ็กซเซฟช่ันเหลาน้ีเปนความผิดพลาดที่เรามักแกไขหรือควบคุมอะไรไมได เราจึงมักไมตองใหความสนใจกับมัน ในขณะท่ีคลาส Exception จัดการความผิดพลาดอ่ืน ๆ ซึ่งที่เหลาทั้งหมดที่เราควบคุมได เราจึงมักทํางานกับคลาสน้ีมากกวา มีเอ็กซเซฟชั่นจํานวนมากท่ีสืบทอดคลาส Exception และบางคลาสไมไดอยูในแพจเกจ java.lang

คลาส RuntimeException จัดการความผิดพลาดเก่ียวกับคณิตศาสตรเชนการหารดวยศูนย ความผิดพลาดเกี่ยวกับการกําหนดคาใหตัวแปรผิดประเภท ความผิดพลาดเก่ียวกับการแคส และความผิดพลาดเก่ียวกับการสงผานตัวแปร เมื่อใดที่โปรแกรมรันแลวเกิดความผิดพลาดเหลานี้ขึ้น จาวาเวอรชัวนแมทชีนจะเรียกเอ็กซเซฟชั่นเหลานี้ออกมาเองโดยอัติโนมัติ ซึ่งเปนผลใหโปรแกรมหยุดทํางาน ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 23 23 23 23 ---- 1 1 1 1 : TestException.java: TestException.java: TestException.java: TestException.java

public class TestException { // (1)

public static void main(String args[]) {int i = 10;int j = 0;System.out.println(i/j);

}}

โปรแกรมนี้มีการหารดวยศูนย ซึ่งผิดหลักคณิตศาสตร ผลที่ไดจากการรันโปรแกรมนี้คือจาวาเวอรชัวนแมทชีนจะหยุดทํางานเมื่อโปรแกรมรันไปถึงบรรทัดที่มีการหารดวยศูนยแลวเรียกคลาสเอ็กซเซฟช่ันเก่ียวกับความผิดพลาดทางคณิตศาสตรที่ชื่อ ArithmeticException ออกมา

เอ็กซเซฟช่ันในกลุม runtimeException มีหลายตัว ตัวที่นาสนใจไดแก ArithmeticException,ArrayIndexOutOfBoundsException (เกี่ยวกับอะเรย), ClassCastException (เกี่ยวกับความเขากันไมไดของตัวแปร)

Page 189: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 23 เอ็กซเซฟชั่น

189

ความผิดพลาดเหลาน้ีในกลุม runtimeException สามารถปองกันลวงหนาได จากการเขียนโปรแกรมที่รัดกุม ตัวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 23 23 23 23 ---- 2 2 2 2 : TestException.java: TestException.java: TestException.java: TestException.java

public class TestException { // (1)

public static void main(String args[]) {int i = 10;int j = 0;if (j != 0) {

System.out.println(i/j);}

}}

ถามีเอ็กซเซฟช่ันในกลุม runtimeException เกิดข้ึนขณะรันโปรแกรม โปรแกรมจะหยุดชงัก แตถาหากเราเขียนโปรแกรมอยางรัดกุม เราไมตองกังวลอะไรเลยกับเอ็กซเซฟช่ันในกลุม runtimeException สวนเอ็กซเซฟชั่นอื่น ๆท่ีเหลือท่ีสืบทอดคลาส Exception เปนเอ็กซเซฟช่ันท่ีปองกันลวงหนาไมได ตัวอยางเชน ดิสกชํารุด เราเรียกเอ็กซเซฟช่ันท่ีเหลือเหลาน้ีวา เอ็กซเซฟช่ันท่ีตองมีการตรวจสอบ จาวาจะบังคับใหเราตรวจสอบเอ็กซเซฟชั่นเหลาน้ีเสมอเมือ่ใดก็ตามทีเ่ราใชคําส่ังท่ีมคีวามเส่ียงตอเอ็กซเซฟช่ันเหลาน้ี ตวอยางเชน

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 23 23 23 23 ---- 3 3 3 3 : TestException.java: TestException.java: TestException.java: TestException.java

import java.io.*;

public class TestException {

public static void main(String args[]) {FileInputStream file ;try {

file = new FileInputStream(“memo.dat”);

} catch (IOException ioe) {System.out.println(“File not found.”);

}}

}

โปรแกรมนี้มีการใชคําสั่ง file = new FileInputStream(“memo.dat”) คําส่ังน้ีเปนการเปดไฟลในฮารดิสกที่ชื่อ memo.dat ซ่ึงอันตราย เพราะไฟลนี้อาจไมมีอยูจริงหรือดิสกอาจกําลังชํารุด ดังนั้นจาวาจะบังคับให

Page 190: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 23 เอ็กซเซฟชั่น

190

เราจัดการกับความผิดพลาดท่ีอาจจะเกิดข้ึนซ่ึงทําไดโดยใสคําส่ังนี้ไวใตบลอค try – catch บลอคน้ีจะละเสียไมได

บลอค try – catch

แทนที่เราจะตรวจสอบความผิดพลาดทุกขั้นทุกตอนของโปรแกรม เราสามารถใชบลอค try ในการครอบกลุมของคําส่ัง เพ่ือดักความผิดพลาด ไมวาความผิดพลาดที่เราตองการดักจะเกิดขึ้นที่จุดใดของกลุมคําสั่ง โปรแกรมจะกระโดดออกจากบลอค try แลวจัดการกับความผิดพลาดน้ันตามคําส่ังท่ีระบุไวในบลอค catch ที่อยูตอทายบลอค try ลองดูตวอยางตอไปน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 23 23 23 23 ---- 4 4 4 4 : TestException.java: TestException.java: TestException.java: TestException.java

public class TestException {

public static void main(String args[]) {int i = 10; //(1)int j = 0; //(2)try {

System.out.println(“Entering try block”);//(3)System.out.println(i+j); // (4)System.out.println(i/j); // (5)System.out.println(i*j); // (6)System.out.println(“Finishing try block”); //(7)

} catch (ArithmeticException ae) { // (8)System.out.println(“Divided by Zero Exception.”); // (9)

}System.out.println(“i is ” + i);// (10)System.out.println(“j is “ + j); // (11)

}}

ในโปรแกรมน้ีเราดัก ArithmeticException ที่อาจเกิดขึ้นตั้งแตคําสั่งในบรรทัด (3) ถึง (7) ดวยการใชบลอค try ครอมคําสั่งทั้งหาบรรทัดไว

เอ็กซเซฟช่ันเกิดข้ึนเม่ือโปรแกรมรันมาถึงบรรทัด (5) ซึ่งมีการหารดวยศูนยเกิดขึ้น โปรแกรมจะกระโดดออกจากบลอค try ทันที ทําใหไมมกีารรันโปรแกรมในบรรทัด (6) และ (7) ตอ จากนั้นโปรแกรมจะมองหาบลอค catch ซ่ึงจัดการ ArithmeticException ซ่ึงก็คือบลอคในบรรทัด (8) แลวรันคําส่ังในบลอคน้ันอันไดแกคําส่ังในบรรทัด (9) คําส่ังในบลอค catch จะเปนคําส่ังอะไรก็ได สวนมากเปนคําสั่งที่ใชบอกผูใชวามีความผิดพลาดเกิดข้ึนในโปรแกรม เม่ือรันคําส่ังในบลอค catch เสร็จหมดแลว โปรแกรมจะออกจากบลอคมารันคําสั่งที่อยูถัด ๆไปในแมธธอส ไดแกคําส่ังในบรรทัด (10) (11)

Page 191: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 23 เอ็กซเซฟชั่น

191

ลักษณะของการประกาศบลอค catch เร่ิมดวยการคําส่ัง catch ตามดวยวงเล็บ ภายในวงเล็บมีชื่อของคลาสของเอ็กซเซฟช่ันท่ีเราตองการจะดัก ตามดวยชื่อตัวแปร ชื่อตัวแปรนี้นี้จะใชชื่ออะไรก็ได ตัวแปรตัวนี้คือตัวแปรอางอิงของคลาสเอ็กซเซฟช่ัน ซึ่งใชชี้อินสแตนทของคลาสเอ็กซเซฟชั่นที่ถูกสรางขึ้นโดยอัตโนมติัเวลาท่ีเกิดเอ็กซเซฟช่ันน้ันข้ึนในโปรแกรม

สังเกตวาเราไมจับคําสั่งในบรรทัด (1) (2) เขาไปไวในบลอค try เนื่องจากการประกาศตัวแปรในแมธธอส ถาตัวแปรเหลาน้ันถูกประการในบลอคของคําส่ัง มันจะคงอยูเฉพาะในบลอคของคําสั่งเทานั้น แตในกรณีน้ีเราตองการแนใจวาคําสั่งในบรรทัด (10) (11) จะรันเสมอไมวาจะเกิดเอ็กซเฟสช่ันหรือไม ดังน้ันเราตองเอาคําส่ังในบรรทัด (10) (11) มาไวนอกบลอค try แตคําสั่งทั้งสองมีการอางถึงตวแปร i และ j ดังน้ันเวลาประกาศตัวแปร iและ j ตองประกาศนอกบลอค try ดวย เพื่อใหตัวแปรทั้งสองคงอยูนอกบลอค try ดวย

บลอค try หนึ่ง ๆสามารถดักเอ็กซเซฟช่ันไดมากกวาหน่ึงชนิด ซ่ึงทําไดโดยการเขียนบลอค catch สําหรับเอ็กซเซฟช่ันแตละตัวท่ีเราตองการจะดักเรียงตอจากบลอค try ไปเร่ือย ๆ ดังตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 23 23 23 23 ---- 5 5 5 5 : TestException.java: TestException.java: TestException.java: TestException.java

import java.io.*;

public class TestException {

public static void main(String args[]) {FileInputStream file ;int i,j;try {

file = new FileInputStream(“memo.dat”);i = 10;j = 0;System.out.println(i/j);

} catch (IOException ioe) {System.out.println(“File not found.”);

} catch (ArithmeticException ae) {System.out.println(“Divided by Zero.”);

} catch (Exception ex) {System.out.println(ex.getMessage());

} finally {System.out.println(“Program finished”);

}}

}

Page 192: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 23 เอ็กซเซฟชั่น

192

ในโปรแกรมนี้มีการดักเอ็กซเซฟชั่นสามตัวดวยกัน คือ IOException, ArithmeticException และ Exception ลําดับของบลอค catch มีความสําคัญดวย กลาวคือถาตองการดักเอ็กซเซฟช่ันมากกวาหน่ึงตัวและมีเอ็กซเซฟช่ันบางตัวเปนเอ็กซเซฟช่ันท่ีสืบทอดกัน เวลาเขียนบลอคเอ็กซเซฟช่ันควรเขียนเรียงจากเอ็กซเซฟช่ันท่ีเปนสับคลาสกอนซูปเปอรคลาส เพราะถาโปรแกรมเจอเอ็กซเซฟชัน่แลวกระโดดออกจากบลอค try มันจะมองหาบลอค catch ซ่ึงจัดการกับเอ็กซเซฟช่ันน้ัน ถามนัเจอบลอค catch ของซูปเปอรคลาสของเอ็กซเซฟชัน่ มันจะรันบลอคน้ันทันที แลวออกจากบลอคโดยไมสนใจบลอค catch อ่ืน ๆท่ีตามมาราวกับวามนัเจอเอ็กซเซฟชัน่ท่ีมนัตองการแลว ในกรณีของโปรแกรมตัวอยาง ถาเราเขียนบลอค catch ของ Exception กอน เน่ืองจาก Exception เปนซูปเปอรคลาสของทุก Exception บลอคน้ีจะดักเอ็กซเซฟช่ัน IOException และ ArithmeticException ไวทั้งหมด ทําใหบลอค IOException และ ArithmeticException เองไมมีวันถูกใชงาน

สังเกตคําส่ังในบลอค catch ของ Exception มีการเรียกแมธธอสของอินสแตนท ex ชื่อ getMessage()แมธธอสนี้ถูกนิยามไวใหในคลาส Exception คาของมันคือขอความมาตรฐานที่อธิบายความผิดพลาดของเอ็กซเซฟขชั่นที่เกิดขึ้น และเน่ืองจากคลาสเอ็กซเซฟช่ันคลาสอ่ืน ๆสืบทอดคลาส Exception ดังนั้นแมธธอสนี้จึงใชไดในทุก ๆ เอ็กซเซฟช่ันดวย ไมใชแตเฉพาะ Exception เทาน้ัน

สังเกตวาคราวนี้หลักบลอค catch บลอคสุดทายมีบลอคใหมชื่อ finally คําสั่งในบลอคนี้จะถูกรันเสมอไมวาจะมีเอ็กซเซฟช่ันอะไรเกิดข้ึนบาง หรือแมแตไมมีเอ็กซเซฟชั่นใด ๆเกิดข้ึน บลอค finally มีไดแคบลอคเดียวและเปนบลอคสุดทายเสมอ

บลอค try – catch ใชดักไดทั้ง เอ็กซเซฟชั่นที่ไมตองมีการตรวจสอบ และเอ็กซเซฟช่ันท่ีตองมีการตรวจสอบ แมวาจาวาจะไมไดบังคับใหมีการดักเอ็กซเซฟชั่นที่ไมตองมีการตรวจสอบ เนื่องจากถาเรามั่นใจวาเราเขียนโปรแกรมไดอยางรัดกุม เอ็กซเซฟช่ันเหลาน่ันจะไมเกิดข้ึน แตถาเราตองการในแนใจจริง ๆ เราก็สามารถใชบลอค try-catch ดักเอ็กซเซฟช่ันท่ีไมตองมีการตรวจสอบ ดวยเพื่อปองกันโปรแกรมหยุดชะงักกลางคัน

คําส่ัง throwภายในบลอค try เราสามารถบังคับใหโปรแกรมกระโดดออกจากบลอคไปยังบลอค catch บลอคไหนก็ไดตามชอบใจดวยการใชคําสั่ง throw ลงดูตวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 23 23 23 23 ---- 6 6 6 6 : TestException.jav: TestException.jav: TestException.jav: TestException.javaaaa

public class TestException {

public static void main(String args[]) {int i,j;try {

i = 10;

Page 193: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 23 เอ็กซเซฟชั่น

193

j = 0;if (j == 0) { // (1)

throw new ArithmeticException(“Divided by 0”);}System.out.println(i/j);

} catch (ArithmeticException ae) {System.out.println(“Divided by Zero.”);

} catch (Exception ex) {System.out.println(“Exception occurs”);

} finally {System.out.println(“Program finished”);

}}

}

ในบรรทัด (1) มีการตรวจสอบเองวา j มีคาเปน 0 หรือไม ถาใชใหโยนเอ็กซเซฟชั่น ArithmethicException สังเกตวาคําส่ัง throw ตามดวยคําสั่ง new และช่ือคลาสคลายกับ คําส่ังในการสรางอินสแตนท เพราะเวลาเกิดเอ็กซเซฟช่ันจาวาเวอรชัวนแมทชีนจะสรางอินสแตนทของคลาสน้ันข้ึนมา นอกจากน้ีตัวแปรที่สงใหกับคลาสจะตองเปนคาคงตัวแบบขอความเสมอ ซึ่งจะไปแทนที่ขอความมาตรฐานที่อยูในแมธธอส getMessage()

คําส่ัง throwsในแมธธอสถามีการใชคําสั่งที่เสี่ยงตอการเกิด เอ็กซเซฟช่ันท่ีตองมีการตรวจสอบ เราตองใสคําส่ังน้ันไวในบลอค tryและดักเอ็กซเซฟช่ันน้ันดวยบลอค catch เสมอ แมแตเอ็กซเซฟชั่นที่ไมตองมีการตรวจสอบก็เชนกัน ถาหากเราไมตองการใหโปรแกรมหยุดชักงักกระทันหันเราก็ตองดักเอ็กซเซฟชั่นที่ไมตองมีการตรวจสอบดวย หากเราขี้เกียจดักเอ็กซเซฟชั่นเหลานี้ในแมธธอสเราสามารถโยนความรับผิดชอบไปใหแมธธอสอ่ืนท่ีเรียกแมธธอสน้ีไดดวยการประกาศคําส่ัง throws ดังตัวอยางตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 23 23 23 23 ---- 7 7 7 7 : TestException.java: TestException.java: TestException.java: TestException.java

class DevidedByZeroDemo {void devidedByZero() throws ArithmeticException {//(1)

int i = 10;int j = 0;System.out.println(i/j);

}}

public class TestException {

Page 194: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 23 เอ็กซเซฟชั่น

194

public static void main(String args[]) {

try { // (2)new DevidedByZeroDemo().devidedByZero();

} catch (ArithmeticException ae) {System.out.println(“Divided by Zero.”);

}

}}

ผลการรันเปนดังน้ี

โปรแกรมน้ีประกอบดวยคลาสสองคลาส คลาสแรกมีแมธธอสชื่อ devideByZero() ซี่งมีการหาร 0 เกิดข้ึน แตไมมีการดักเอ็กซเซฟช่ัน เนื่องจากเราสั่งใหโยนความรับผิดชอบไปใหแมธธอสใดก็ตามที่เรียกมัน ในคลาสท่ีสองคือคลาสหลักของโปรแกรม ซึ่งมีแมธธอส main() อยู แมธธอส main() เรียกแมธธอส devideByZero() ในคลาสแรก ดงนั้นมันจึงตองดักเอ็กซเซฟชั่นแทนแมธธอส devideByZero การโยนความรับผิดชอบแบบนี้สามารถทําตอ ๆกันไปไดเปนงูกินหาร แตทายที่สุดแลวตองมีแมธธอสที่รับหนาที่นี้ไปมิฉะนั้นคอมไพลเลอรจะฟองความผิดพลาดออกมา

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

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

public static void x(int i) throws IOException

ตัวอยางนี้ แมธธอส x() มีความเสี่ยงที่จะเกิด IOException ดังนั้นคอนแทร็กของแมธธอส x() จึงตองมีคําวา throws ตามดวยชื่อเอ็กซเซฟชั่นที่ตองตรวจสอบคือ IOException

C:\java> java TestExceptionDivided by Zero.

Page 195: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 23 เอ็กซเซฟชั่น

195

เอ็กซเซฟช่ันท่ีเราสรางเองเราสามารถสรางคลาสเอ็กซเซฟช่ันข้ึนมาดักความผิดพลาดเองไดดวยการสืบทอดคลาส Exception และเอ็กซเซฟช่ันท่ีเราสรางข้ึนมาสามารถสืบทอดกันเปนช้ัน ๆไดอีกดวย ลองดูตัวอยางตอไปน้ี

โโโโปรแกรม ปรแกรม ปรแกรม ปรแกรม 23 23 23 23 ---- 8 8 8 8 : TestException.java: TestException.java: TestException.java: TestException.java

class FirstException extends Exception { } // (1)class SecondException extends FirstException { }// (2)public class TestException {

public static void main(String args[]) {int i;try {

i = 1;if (i == 1) throw new FirstException();if (i == 2) throw new SecondException();

} catch (SecondException e) {System.out.println(e.getMessage());

} catch (FirstException e) {System.out.println(e.getMessage());

}}

}

ในบรรทัด (1) เปนการสรางเอ็กซเซฟช่ันข้ึนเองช่ือ FirstException สวนในบรรทัด (2) เปนการสรางเอ็กซเซฟช่ันเองอีกเปนตัวท่ีสองโดยสืบทอดตัวแรก

ในกรณีน้ีเวลาดักเอ็กซเซฟช่ัน ตองดัก SecondException กอน FirstException เพราะ SecondException สืบทอดมาจาก FirstException

Page 196: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม
Page 197: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

24 เทรด

บนจาวาเวอรชัวนแมทชีนโปรแกรมหนึ่งโปรแกรมที่เรารันเรียกวา โปรเซส ซึ่งการทํางานของโปรแกรมจะเริ่มรันจากแมธธอส main() ถามีการเรียกแมธธอสอื่น ๆโปรแกรมก็จะรันตอไปเรื่อยๆ จนกลับมาสิ้นสุดที่แมธธอส main()แมธธอส main() รันเสร็จส้ินเม่ือใดโปรเซสหรือโปรแกรมน้ันก็จะหยุดทํางาน

ในโปรเซสหน่ึงโปรเซสเราสามารถเขียนโปรแกรมใหรันไดมากกวาหน่ึงเสนทาง หมายความวา จากเดิมที่รันแมธธอส main() อยางเดียวจนจบ ก็อาจจะรันแมธธอสอื่นไปพรอม ๆกับแมธธอส main() ไดดวย เราเรียกเสนทางเหลานี้วา เทรด

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

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

Page 198: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 24 เทรด

198

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

เวลาเร่ิมรันโปรแกรม โปรแกรมทุกโปรแกรมจะเริ่มรันที่แมธธอส main() ซ่ึงก็คือเทรดเทรดแรกของโปรแกรม หรือเราเรียกวาเทรดหลัก ถาไมมีการสรางเทรดเพ่ิมเติม โปรแกรมจะรับแมธธอส main() อยางตอเนื่องไปจนจบ โปรแกรมแบบนี้มีเทรดเดียว แตถามีคําสั่งสรางเทรดเพิ่มเติมในแมธธอส main() ก็จะเกิดเทรดลูกขึ้น เทรดลูกจะรันเปนอิสระจากเทรดหลัก และอาจเสร็จกอนหรือหลังเทรดหลักก็ได ถาเสร็จทีหลัง เทรดหลักจะจบไปกอน แตโปรแกรมจะรันตอไปเรื่อย ๆจนกวาเทรดลูกทุกเทรดจะเสร็จจึงจบโปรแกรม

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

คลาส Threadเราสามารถเขียนโปรแกรมใหมีมากกวาหนึ่งเทรดไดดวยการสรางคลาสทีสื่บทอดคลาส Thread ขึ้นมา คลาส Thread มีมาใหอยูแลวในภาษาจาวา เราอางถึงทันทีโดยไมตองมีการอิมพอรตแพจเกจใด ๆ ลองดูตวอยางการสรางเทรดลูกดวยการสรางคลาสท่ีสืบทอดคลาส Thread ดังตอไปน้ี

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 24 24 24 24 ---- 1 1 1 1 : TestThread.java: TestThread.java: TestThread.java: TestThread.java

class MyThread extends Thread { // (1)

private int counter;private int delay;

public MyThread(String threadName, int counter, int delay) {super(threadName); // (2)this.counter = counter;this.delay = delay;System.out.println(threadName + " started.");

}

public void run() { // (3)try {

while(counter > 0) {System.out.println(getName() +": "+ counter--); // (4)Thread.sleep(delay); // (5)

Page 199: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 24 เทรด

199

} catch (InterruptedException e) {}System.out.println (getName() + " ended.");

}}

public class TestThread {

public static void main(String args[]) {System.out.println("Main thread started.");new MyThread("A",10,100).start(); // (6)new MyThread("B",5,200).start(); // (7)

System.out.println("Main thread ended.");

}}

ในบรรทัด (1) เราสรางคลาสช่ือ MyThread โดยสืบทอดคลาส Thread

บรรทัด (2) ในคอนสตรัสเตอรของ MyThread เราเรียกคอนสตรัสเตอรของคลาส Thread แบบมีการตั้งชื่อเทรดดวย เราสามารถตั้งชื่อเทรดแตละตัวเราสรางขึ้นไดดวยวิธีนี้ ถาตองการ

ในบรรทัด (3) เม่ือเราสรางคลาสท่ีสืบทอดคลาส Thread ขึ้นมาแลว สิ่งที่เราตองการใหเทรดรันจะอยูภายใตแมธธอสชื่อ run() ของคลาสน้ัน ๆ เทรดตายเมื่อแมธธอส run() ส้ินสุด เราโอเวอรรายดแมธธอส run()ของคลาส Thread ใหทํางานอะไรก็ไดตามใจชอบ ในกรณีน้ีเราลดเคานเตอรทีละหน่ึง โดยแตละครั้งเวนหางกัน เทากับจํานวนมิลลิวินาทีที่ระบุไวในแมธธอส sleep()ในบรรทัด (5) แมธธอสน้ีเปนแมธธอสสแตรติกของคลาส Thread ซึ่งรับตัวแปรเปนจํานวนเต็มเทากับเวลาที่ใหรอ เมื่อโปรแกรมรันมาถึงแมธธอสนี้มันจะคืนหนวยประมวลผลใหแลวหยุดทํางานเปนเวลาเทากับที่ระบุไว แลวคอยกลับมาทํางานตอ โปรแกรนี้จึงวิ่ง ๆ หยุด ๆ ไปเร่ือย ๆจนกวาเคานเตอรจะมีคานอยกวา 0

ในบรรทัด (4) มีการเรียกแมธธอสชื่อ getName() เปนแมธธอสในคลาส Thread ท่ีสงช่ือของเทรดท่ีเราเคยตั้งไวออกมา ถาเราไมไดตั้งไว มันจะตั้งชื่อของมันเอง

เน่ืองจากคําส่ัง sleep() เปนคําส่ังท่ีอาจทําใหเกิดเอ็กซเซฟช่ัน InterruptedException ได เราจงึตองจับใสไวในบลอค try ดวย

ในแมธธอส main() เราสรางเทรดลูกข้ึนมาสองเทรด ซ่ึงทําไดโดยการสรางอินสแตนทของคลาส MyThreadแลวเรียกแมธธอส start() ในบรรทัด (6) (7) สิ่งที่เกิดขึ้นก็คือแมธธอส run() จะเริ่มทํางานโดยอิสระ

Page 200: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 24 เทรด

200

ผลการรันโปรแกรมอาจเปนไปไดหลายแบบ เพราะเราไมอาจทํานายไดวาเทรดทั้งสองจะเสร็จเมื่อไหร เมือ่เทรดนอนหลับจนถึงเวลาที่กําหนดแลว ทุกอยางจะขึ้นอยูกับจาวาเวอรชัวนแมทชีนที่จะยกหนวยประมวลผลใหเทรดน้ันหรือไมก็ได ตัวอยางที่เปนไปไดอยางหนึ่งของผลการรันโปรแกรมขางตนเปนดังนี้

ขอใหสังเกตวาเทรดหลักตายเม่ือสรางเทรดลูกเสร็จ สวนเทรดลูกจะรันตอไปเร่ือย ๆจนจบ เมือ่เทรดลูกรันเสร็จหมดทุกเทรดแลวโปรแกรมจึงจบโดยสมบูรณ

อินเตอรเฟส Runnableเราสามารถสรางเทรดไดอีกวิธีหน่ึงคือการสรางคลาสท่ีสืบทอดอินเตอรเฟส Runnable วิธีน้ีดีกวาวิธีสืบทอดคลาส Thread ตรงท่ีถาคลาสของเราตองการสืบทอดคลาสอ่ืนดวยก็สามารถทําได การสืบทอดคลาส Thread ตัดโอกาศคลาสในการสืบทอดคลาสอ่ืน และทําใหคลาสมีขนาดใหญเกินจําเปนเพราะตองสืบทอดตัวแปรและแมธธอสทุกตัวในคลาส Thread เขามา ทั้งที่อาจไมไดใช

อินเตอรเฟส Runnable มีแมธธอสชื่อ run() อยูเชนเดียวกัน แตวิธีการสรางเทรดแตกตางกันเล็กนอย ลองดูตัวอยางดังตอไปนี้

โปรแกรม โปรแกรม โปรแกรม โปรแกรม 24 24 24 24 ---- 2 2 2 2 : TestThread.java: TestThread.java: TestThread.java: TestThread.java

class MyThread implements Runnable { // (1)

private int counter;private int delay;

Page 201: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 24 เทรด

201

private Thread thread; // (2)

public MyThread(String threadName, int counter, int delay) {this.counter = counter;this.delay = delay;thread = new Thread(this, threadName); // (3)thread.start();// (4)System.out.println(threadName + " started.");

}

public void run() {try {

while(counter > 0) {System.out.println(thread.getName() +": "+ counter--

); // (5)Thread.sleep(delay);

}} catch (InterruptedException e) {}System.out.println (thread.getName() + " ended."); // (6)

}}

public class TestThread {

public static void main(String args[]) {System.out.println("Main thread started.");new MyThread("A",10,100);new MyThread("B",5,200);

System.out.println("Main thread ended.");

}}

โปรแกรมนี้จะใหผลเหมือนโปรแกรมที่ผานมา

ในบรรทัด (1) เราสืบทอดอินเตอรเฟส Runnable แทนท่ีจะเปนคลาส Thread

คราวน้ีเราประกาศวัตถุของคลาส Thread ในบรรทัด (2) แทนการสืบทอดคลาส Thread และในบรรทัด (3)เราเรียกคอนสตรัคเตอรตัวหน่ึงของคลาส Thread ซึ่งคราวนี้มีตัวแปรสงเขาสองตัว ตัวแรกคือวัตถุที่ตองการใหรันแมธธอส run() ของมันหลังจากเรียกแมธธอส start() ซ่ึงในกรณีน้ีคือตัวคลาส MyThread เอง เราจึงสงคําวา this เขาไป สวนตัวแปรตัวที่สองที่สงเขาไปก็คือชื่อที่เราตั้งใหเทรดเหมือนเคย

เรายายมาเรียกแมธธอส start() ในตัวเทรดเอง ในบรรทัด (4)

Page 202: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 24 เทรด

202

สังเกตวาคราวนี้เวลาเรียกแมธธอส getName() ในบรรทัด (5) (6) เราตองระบุชื่อดวย เพราะมันไมใชแมธธอสของคลาส MyThread เหมือนอยางในกรณีของการสืบทอดคลาส Thread

คําส่ัง synchronizedเทรดในโปรเซสเดียวกับจะแชรพื้นที่ในแรมรวมกัน นั้นหมายถึงมันจะรันแมธธอสจากแมธธอสตัวเดียวกันที่โหลดไวในแรม เน่ืองจากเทรดแตละเทรดรันอยางเปนอิสระตอกัน เราไมสามารถทํานายไดเลยวาเม่ือไร เทรดตัวไหนจะรันแมธธอสใด และก็เปนไปไดดวยท่ีเทรดสองเทรดหรือมากกวาจะกําลังแมธธอสเดียวกนัอยู

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

เราล็อกแมธธอสไดดวยการประกาศใหเปนแมธธอส synchronized ตัวอยางเชน

void synchronized update() {

}

น้ันคือเราใชคําส่ัง synchronized นําหนาแมธธอสน้ัน ๆ ถามีเทรดใดมารันแมธธอสนี้ มันจะล็อคไมใหเทรดอื่นเขามารัน ทําใหเทรดอ่ืนตองรอไปกอน และในเวลาเดียวกันมันจะล็อกแมธธอสอ่ืน ๆในคลาสเดียวกันท่ีถูกประกาศเปน synchronized ดวย เทรดเดียวที่สามารถรันแมธธอสเหลานั้นไดคือเทรดที่กําลังรันแมธธอส synchronized อยูเทาน้ัน แตอยางไรก็ตามแมธธอสอื่นในคลาสที่ไมถูกประกาศใหเปน synchronized จะไมถูกล็อคไปดวย

เราสามารถใชคําส่ัง synchronized กับแมธธอสสแตรติกไดดวย แตในกรณีนี้ถามีเทรดใดเขาใชแมธธอสนั้นมันจะล็อคแมธธอสนั้นและแมธธอสสแตรติกตัวอื่นในคลาสที่เปน synchronized เทาน้ัน ไมรวมถึงแมธธอสอินสแตนทที่เปน synchronized ดวย

Page 203: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

ดรรชนี? :, 53100% pure java, 7args, 115boolean, 28break, 58byte, 27char, 28continue, 59double, 28float, 28for, 56if, 45instanceof, 165int, 27JAVA_HOME, 13JRE, 12long, 27Math, 121Object, 163Path, 13Private, 157protected, 161public, 161SDK, 12short, 27sourcepath, 17

super(), 134switch, 51synchronized, 202while, 54Write Once, Run Anywhere, 7

การแคส, 34การสรางอินสแตนท, 65การโอเวอรรายด, 129การโอเวอรโหลดแมธธอส, 93คลาส, 19, 62คลาสถาวร, 128คลาสนามธรรม, 127คลาสสาธารณะ, 148คอนแทร็คของคลาส, 156คอนสตรัคเตอร, 99คอนสตรัคเตอรโอเวอรโหลด, 102คอนสตรัสเตอรปกติ, 102

คอลเล็กชั่น, 173คาคงตัว, 24คาคงตัวขอความ, 27คาคงตัวจํานวนเต็มแบบยาว, 25คาคงตัวจํานวนเต็มปกติ, 25คาคงตัวตรรก, 26คาคงตัวตัวอักษร, 26คาคงตัวทศนิยมแบบยาว, 25คาคงตัวทศนิยมปกติ, 25คุณสมบัติของวัตถุ, 62เคร่ืองหมายอินครีเมนท, 40จาวาคอมไพลเลอร, 8จาวาไบตโคด, 8จาวาเวอรชัวนแมทชีน, 6ซอรสโคด, 8ซูปเปอรคลาส, 125เซต, 175ตัวกํากับตัวแปรคลาส และแมธธอส, 157ตัวแปร, 27ตัวแปรคลาส, 62ตัวแปรทองถิ่น, 76ตัวแปรอางอิง, 67เทรด, 197เทรดงาน, 198เทรดลูก, 198เทรดสนับสนุน, 198เทรดหลัก, 198บลอกของคําส่ัง, 46โปรแกรมรีเคอรซีฟ, 91โปรเซส, 197พฤติกรรมของวัตถุ, 62แพจเกจ, 145แพจเกจมาตรฐาน, 155แฟลตฟอรม, 6แมธธอส, 20, 62

Page 204: เขียนโปรแกรมเชิงวัตถุด วยpittajarn.lpru.ac.th/~nukit/java/java2.pdfปฏ บ ต การว าเป น แฟลตฟอร ม

บทที่ 24 เทรด

204

แมธธอสถาวร, 133แมธธอสนามธรรม, 134แมธธอสสแตรติก, 96แม็บ, 181ลิสต, 177วัตถุ, 65สมาชิกของคลาส, 62สวนตัวของคลาส, 20สวนตัวของแมธธอส, 20สวนหัวของคลาส, 20

สวนหัวของแมธธอส, 20สับคลาส, 125สับแพจเกจ, 151อะเรย, 81อินเตอรเฟส, 169อินสแตนท, 65อินสแตนทของคลาส, 65อิมพลีเมนทเทชั่นของคลาส, 156เอ็กซเซฟชั่น, 187โอค, 6