Module : java.base  / Package : java.lang

public class Object

คลาส Object เป็นคลาสต้นฉบับของทุกๆคลาสในโลกของภาษาจาวา การสร้างออบเจกต์จากคลาส Object ทำได้โดยใช้เมธอดคอนสตรัคเตอร์ Object() ตัวอย่างเช่น Object object = new Object() เนื่องจากคลาส Object เป็นคลาสต้นฉบับของทุกๆคลาส ดังนั้นคลาสอื่นๆจึงมีค่าตั้งต้นของเมธอดคอนสตรัคเตอร์ในทำนองเดียวกันแม้ว่าเราจะไม่ได้สร้างเมธอดคอนสตรัคเตอร์ขึ้นมาในคลาสนั้นๆ ตัวอย่างเช่น หากเราสร้างคลาส MyClass ขึ้นมา คลาส MyClass จะมีเมธอดคอนสตรัคเตอร์ที่เป็นค่าตั้งต้น (default constructure method) คือ MyClass myclass = new MyClass() 

     จากตัวอย่างด้านล่างในบรรทัดที่ 7 เราสร้างคลาส MyClass ขึ้นมาโดยไม่ได้ระบุอะไรไว้เลย แต่ในบรรทัดที่ 3 เราสามารถใช้เมธอดคอนสตรัคเตอร์ในทำนองเดียวกันกับคลาส Object ในการสร้างออบเจกต์ MyClass ได้ด้วยทั้งที่ไม่ได้เขียนไว้ในคลาสซึ่งเป็นผลจากการสืบทอดมาจากคลาส Object

     คลาส Object ประกอบด้วยเมธอด clone(), equals(Object obj), getClass(), hashCode(), notify(), notifyAll(), toString(), wait(), wait(long timeoutMillis), wait(long timeoutMillis, int nanos) ซึ่งเมธอดเหล่านี้จะสืบทอดไปยังทุกๆคลาสใน Java API รวมถึงคลาสใหม่ที่เราสร้างขึ้นมา และเรามักจะต้องโอเวอร์ไรด์เมธอด clone(), equals(Object obj), hashCode() และ toString() ให้เหมาะสมกับคลาสของเรา

เมธอด clone() 

     เป็นการสำเนาออบเจกต์โดยได้ผลลัพธ์ออกมาเป็นออบเจกต์ใหม่ คลาสที่จะสืบทอดเมธอดนี้ไปใช้จะต้อง implement คลาสอินเตอร์เฟส Cloneable และต้องโอเวอร์ไรด์เมธอด clone() ซึ่งเป็นการบังคับให้เรากำหนดว่าจะสำเนาออบเจกต์ของเราอย่างไร จากตัวอย่างด้านบน ถ้าเราเรียกเมธอดจะพบว่าไม่มีเมธอด clone() แสดงในรายการเมธอด

     แต่เมื่อเรา implement คลาสอินเตอร์เฟส Cloneable และโอเวอร์ไรด์เมธอด clone() จะเห็นเมธอด clone() แสดงในรายการเมธอด

     สำเนาออบเจกต์ที่ได้จากการ clone() จะเป็นอิสระจากออบเจกต์ต้นฉบับ ซึ่งสามารถอธิบายในมุมมองของการเป็น reference data type ว่าทั้ง 2 ออบเจกต์จะถูกเก็บไว้คนละที่ของหน่วยความจำ เราพิสูจน์เรื่องนี้ได้โดยใช้อาเรย์ซึ่งรองรับการใช้เมธอด clone() ตามตัวอย่างด้านล่าง เราสำเนา arrayInt2 จาก arrayInt1 โดยใช้เมธอด clone() จะเห็นว่าเราสามารถแก้ไขค่าใน arrayInt2[0] โดยไม่กระทบกับค่าใน arrayInt1[0] แสดงว่าตัวแปรชี้ไปที่คนละที่ของหน่วยความจำ(เป็นออบเจกต์คนละตัวกันจริงๆ)

     สำหรับคลาสใน Java API เช่นอาเรย์ ที่สามารถใช้เมธอด clone() ได้เนื่องจากมีการ implement คลาสอินเตอร์เฟส Cloneable และโอเวอร์ไรด์เมธอด clone() เรียบร้อยแล้ว

เมธอด equals(Object obj)

     เป็นการเปรียบเทียบว่าออบเจกต์อื่นเท่ากับตัวเองหรือไม่ โดยให้ผลลัพธ์เป็นค่าจริงหรือเท็จ (boolean) การเปรียบเทียบว่า “equal” หรือไม่นั้นจะเป็นไปตามเงื่อนไขด้านล่าง 

  • เมื่อ x ไม่ใช่ null  / x.equals(x) จะต้องเป็นจริง
  • เมื่อ x, y ไม่ใช่ null  / x.equals(y) จะเป็นจริงก็ต่อเมื่อ y.equals(x) เป็นจริง
  • เมื่อ x, y, z ไม่ใช่ null  / ถ้า x.equals(y) เป็นจริง และ y.equals(z) เป็นจริง แล้ว x.equals(z) จะต้องเป็นจริง
  • เงื่อนไขด้านบนจะต้องให้ผลลัพธ์เหมือนเดิมเสมอไม่ว่าจะลองกี่ครั้งก็ตาม ตราบเท่าที่ไม่มีการเปลี่ยนแปลงของข้อมูล
  • และ x.equals(null) จะต้องเป็นเท็จ

    การใช้งานเมธอด equals() ของคลาส Object จะให้ผลเป็นจริงก็ต่อเมื่อเป็นออบเจกต์เดียวกัน คือ object1.equals(object2) เป็นจริงเมื่อ object1 == object2 เป็นจริง ซึ่งหากคลาสที่เราสร้างขึ้นมาสืบทอดเมธอด equals() มาใช้โดยตรงอาจจะไม่ตรงกับความต้องการ ดังนั้นจึงต้องโอเวอร์ไรด์เมธอด equals() ให้เหมาะสม และเมื่อเราโอเวอร์ไรด์เมธอด equals() แล้วเราต้องโอเวอร์ไรด์เมธอด hashCode() ด้วย เพราะเมธอด hashCode() ของคลาส Object จะให้ค่า hash code ที่ตรงกันเมื่อเป็นออบเจกต์เดียวกันเท่านั้น จึงต้องโอเวอร์ไรด์ให้เหมาะสม ไม่เช่นนั้นอาจส่งผลให้การทำงานกับบางคลาสไม่ถูกต้อง สำหรับคลาสอื่นๆใน Java API เช่น คลาส String สามารถใช้เมธอด equals() ได้อย่างถูกต้องเนื่องจากมีการโอเวอร์ไรด์เรียบร้อยแล้ว 

     จากตัวอย่างด้านล่างเป็นการโอเวอร์ไรด์คลาสที่สร้างขึ้นมาเองแบบง่ายๆ โดยคลาส MyClass จะมีเพียงฟิลด์ mytext เพื่อเก็บข้อความ และเรากำหนดว่าออบเจกต์ที่เก็บข้อความเหมือนกันเราจะถือว่า “equal”  ถึงแม้ว่าจะเป็นคนละออบเจกต์ก็ตาม ดังนั้นเราต้องโอเวอร์ไรด์เมธอด equals() ดังบรรทัดที่ 20 – 28 โดยบรรทัดที่ 21 เป็นการตรวจสอบว่าเป็นออบเจกต์เดียวกันหรือไม่ บรรทัดที่ 24 ตรวจสอบว่าเป็นออบเจกต์ MyClass หรือไม่ บรรทัดที่ 28 เปรียบเทียบข้อความที่เก็บว่าตรงกันหรือไม่ 

     สำหรับการโอเวอร์ไรด์ hashCode() ในบรรทัดที่ 32 เราใช้ค่าที่ได้จากการใช้เมธอด hashCode() ของคลาส String ซึ่งถ้าข้อความเหมือนกันจะได้ค่า hash code เดียวกัน

เมธอด getClass()

     เป็นเมธอดที่ให้ผลลัพธ์เป็นออบเจกต์ Class ซึ่งเป็นออบเจกต์ที่ใช้เก็บข้อมูลคลาสของออบเจกต์ที่เรียกใช้เมธอด getClass() เราสามารถตรวจสอบและตั้งค่าต่างๆของคลาสได้โดยใช้เมธอดของคลาส Class 

     จากตัวอย่างด้านล่าง เราใช้เมธอด getClass() กับคลาสที่สร้างขึ้นมาและใช้เมธอดของคลาส Class เพื่อดูข้อมูล เช่น ชื่อคลาส ชื่อแพคเกจ เป็นต้น

เมธอด hashCode()

     เป็นเมธอดที่คืนค่า hash code เป็นเลขจำนวนเต็ม (int) โดยออบเจกต์ที่เหมือนกันในความหมายว่า  obj1.equals(obj2) เป็นจริง หรือ obj1 == obj2 เป็นจริง จะต้องมีเลข hash code ที่เหมือนกัน 

     จากตัวอย่างด้านล่าง จะเห็นว่า obj1 และ obj3 มีค่า hash code เท่ากันและเปรียบเทียบด้วยเมธอด equals() มีค่าเป็นจริง

     ในกรณีที่เราโอเวอร์ไรด์เมธอด equals() ให้รองรับกับคลาสที่สร้างขึ้นมา เราต้องโอเวอร์ไรด์เมธอด hasCode() ให้สอดคล้องกันด้วย โดยออบเจกต์ที่  “equal” จะต้องมีค่า hash code  ที่เหมือนกัน

เมธอด toString()

     เป็นเมธอดที่ใช้คืนค่าเป็นข้อความ (String) เพื่ออธิบายว่าแต่ละออบเจกต์คืออะไร เมธอด toString() ของคลาส Object จะคืนค่าเป็นข้อความที่ประกอบด้วย  “ชื่อคลาส@ค่า hash code ของแต่ละออบเจกต์” เราควรจะโอเวอร์ไรด์เมธอด toString() เพื่อให้เหมาะสมกับคลาสของเรา ตัวอย่างเช่น  ในบรรทัดที่ 21 – 23 เราโอเวอร์ไรด์เมธอด toString() เพื่อแสดงข้อความที่เก็บไว้ในออบเจกต์

     บรรทัดที่ 5 เราสร้างออบเจกต์เพื่อเก็บคำว่า Java และพิมพ์ข้อความที่บอกว่าออบเจกต์นั้นคืออะไรด้วยเมธอด toString()

เมธอด notify() notifyAll() และ wait()

     เมธอด wait() เป็นเมธอดที่ใช้สั่งให้เธรดพักการทำงาน เมธอด nofity() ใช้สำหรับแจ้งให้เธรดตามที่ระบุกลับมาทำงานหลังจากถูกสั่งให้พัก เมธอด notifyAll() ใช้สำหรับแจ้งให้ทุกเธรดกลับมาทำงานหลังจากถูกสั่งให้พัก รายละเอียดสามารถดูได้จาก https://marupatnote.home.blog/2022/08/24/java-concurrency/