کلاس Object در پکیج java.lang در بالای درخت سلسلهمراتب کلاسها قرار دارد. هر کلاسی — مستقیم یا غیرمستقیم — فرزند Object است. هر کلاسی که استفاده یا مینویسید، متدهای instance Object را به ارث میبرد. لازم نیست از هیچکدام از این متدها استفاده کنید، اما اگر بخواهید این کار را انجام دهید، ممکن است نیاز باشد آنها را با کدی که مخصوص کلاس شماست بازنویسی کنید. متدهای به ارثرسیده از Object که در این بخش مورد بحث قرار میگیرند عبارتند از:
protected Object clone() throws CloneNotSupportedException: یک کپی از این شی ایجاد و برمیگرداند.public boolean equals(Object obj): نشان میدهد آیا شی دیگری «برابر» با این شی است یا خیر.protected void finalize() throws Throwable: هنگامی توسط Garbage Collector روی یک شی فراخوانی میشود که Garbage Collection تشخیص دهد ارجاع دیگری به شی وجود ندارد. از جاوا ۱۸ این متد برای حذف علامتگذاری شده (Deprecated for Removal) است.public final Class getClass(): کلاس زمان اجرایی یک شی را برمیگرداند.public int hashCode(): مقدار Hash Code شی را برمیگرداند.public String toString(): نمایش رشتهای شی را برمیگرداند.توجه کنید که از جاوا SE 9 متد finalize() Deprecated شده و از جاوا SE 18 Deprecated for Removal شده است. بازنویسی این متد اکیداً توصیه نمیشود. در زمانی نامعلوم دیگر فراخوانی نخواهد شد. برای اطلاعات بیشتر آخرین بخش این صفحه را ببینید.
متدهای notify()، notifyAll() و wait() کلاس Object همگی در هماهنگسازی فعالیت Threadهای مستقل در یک برنامه نقش دارند که در بخش بعدی مورد بحث قرار خواهد گرفت و اینجا پوشش داده نمیشوند. پنج متد اینچنینی وجود دارد:
public final void notify()public final void notifyAll()public final void wait()public final void wait(long timeout)public final void wait(long timeout, int nanos)---نکته: جنبههای ظریفی در تعدادی از این متدها وجود دارد، بهویژه متد clone.
همیشه باید بازنویسی متد toString() در کلاسهایتان را در نظر بگیرید.
متد toString() کلاس Object نمایشی از نوع String شی را برمیگرداند که برای دیباگ بسیار مفید است. نمایش رشتهای یک شی کاملاً به خود شی بستگی دارد و به همین دلیل است که باید toString() را در کلاسهایتان بازنویسی کنید.
میتوانید toString() را همراه IO.println() استفاده کنید تا نمایش متنی یک شی را نشان دهید، مثل یک نمونه از Book:
IO.println(firstBook.toString());
که در صورتی که متد toString() بهدرستی بازنویسی شده باشد، چیز مفیدی مثل این را چاپ میکند:
ISBN: 0201914670; The Swing Tutorial; A Guide to Constructing GUIs, 2nd Edition
---
متد equals() دو شی را از نظر برابری مقایسه میکند و اگر برابر باشند true برمیگرداند. متد equals() ارائهشده در کلاس Object از عملگر همانندی (==) برای تعیین اینکه آیا دو شی برابر هستند استفاده میکند. برای انواع دادهای اولیه (Primitive) این نتیجهی درستی میدهد. اما برای اشیا، اینطور نیست. متد equals() ارائهشده توسط Object بررسی میکند آیا ارجاعات شی برابرند — یعنی آیا اشیای مقایسهشده دقیقاً یک شی واحد هستند.
برای بررسی اینکه آیا دو شی در معنای همارزی (شامل اطلاعات یکسان) برابر هستند، باید متد equals() را بازنویسی کنید. مثالی از کلاس Book که equals() را بازنویسی میکند:
public class Book {
String ISBN;
public String getISBN() {
return ISBN;
}
public boolean equals(Object obj) {
return obj instanceof Book book && ISBN.equals(book.getISBN());
}
}
کدی که دو نمونه از کلاس Book را برای برابری بررسی میکند را در نظر بگیرید:
// Swing Tutorial, 2nd edition
Book firstBook = new Book("0201914670");
Book secondBook = new Book("0201914670");
if (firstBook.equals(secondBook)) {
IO.println("objects are equal");
} else {
IO.println("objects are not equal");
}
این برنامه «objects are equal» نمایش میدهد حتی اگر firstBook و secondBook به دو شی متفاوت ارجاع دهند. آنها برابر در نظر گرفته میشوند چون اشیای مقایسهشده حاوی شماره ISBN یکسانی هستند.
اگر عملگر همانندی برای کلاس شما مناسب نیست، همیشه باید equals() را بازنویسی کنید.
---نکته: اگر
equals()را بازنویسی میکنید، بایدhashCode()را هم بازنویسی کنید.
مقداری که توسط hashCode() برگردانده میشود، Hash Code شی است — مقداری عددی که توسط الگوریتم Hashing تولید میشود.
طبق تعریف، اگر دو شی برابر باشند، Hash Code آنها هم باید یکسان باشد. اگر متد equals() را بازنویسی کنید، شیوهی مقایسهی برابری دو شی تغییر میکند و پیادهسازی Object برای hashCode() دیگر معتبر نخواهد بود. بنابراین اگر equals() را بازنویسی میکنید، باید hashCode() را هم بازنویسی کنید.
متد getClass() قابل بازنویسی نیست.
متد getClass() یک شی از نوع Class برمیگرداند که متدهایی دارد که میتوانید از آنها برای دریافت اطلاعاتی درباره کلاس استفاده کنید، مثل نام کلاس (getSimpleName())، فوقکلاس (getSuperclass())، و Interfaceهای پیادهسازیشده (getInterfaces()). مثال زیر نام کلاس یک شی را دریافت و نمایش میدهد:
void printClassName(Object obj) {
IO.println("The object's class is " +
obj.getClass().getSimpleName());
}
کلاس Class در پکیج java.lang تعداد زیادی متد (بیش از ۵۰) دارد. مثلاً میتوانید بررسی کنید کلاس یک Annotation است (isAnnotation())، یک Interface است (isInterface())، یا یک Enum است (isEnum()). میتوانید ببینید فیلدهای شی چیست (getFields()) یا متدهایش چیست (getMethods())، و غیره.
اگر یک کلاس، یا یکی از فوقکلاسهایش، Interface Cloneable را پیادهسازی کرده باشد، میتوانید از متد clone() برای ایجاد کپی از یک شی موجود استفاده کنید. برای ایجاد یک Clone بنویسید:
aCloneableObject.clone();
پیادهسازی Object برای این متد بررسی میکند آیا شیای که clone() روی آن فراخوانی شده Interface Cloneable را پیادهسازی کرده است یا نه. اگر شی این Interface را پیادهسازی نکرده باشد، متد CloneNotSupportedException پرتاب میکند. مدیریت Exception در بخش Exception پوشش داده خواهد شد. فعلاً باید بدانید که clone() باید به صورت زیر اعلان شود
protected Object clone() throws CloneNotSupportedException
یا
public Object clone() throws CloneNotSupportedException
اگر قصد دارید متد clone() بنویسید تا متد موجود در Object را بازنویسی کند.
اگر شیای که clone() روی آن فراخوانی شده Interface Cloneable را پیادهسازی کرده باشد، پیادهسازی Object برای متد clone() شیای از همان نوع شی اصلی ایجاد میکند و متغیرهای عضو شی جدید را با مقادیر متغیرهای عضو متناظر شی اصلی مقداردهی اولیه میکند.
سادهترین راه برای Cloneable کردن کلاس شما، اضافه کردن implements Cloneable به اعلان کلاس شماست. سپس اشیای شما میتوانند متد clone() را فراخوانی کنند.
برای برخی کلاسها، رفتار پیشفرض متد clone() کلاس Object کاملاً مناسب است. اما اگر شی شامل ارجاعی به شی خارجی باشد، مثلاً ObjExternal، ممکن است نیاز باشد clone() را بازنویسی کنید تا رفتار صحیحی داشته باشید. در غیر این صورت، تغییری که توسط یک شی در ObjExternal ایجاد شود، در Clone آن شی هم قابل مشاهده خواهد بود. این یعنی شی اصلی و Clone آن مستقل نیستند — برای جدا کردن آنها باید clone() را بازنویسی کنید تا هم شی و هم ObjExternal را کپی کند. سپس شی اصلی به ObjExternal ارجاع میدهد و Clone به یک کپی از ObjExternal ارجاع میدهد و بدین ترتیب شی و Clone آن واقعاً مستقل خواهند بود.
کلاس Object متد callback به نام finalize() فراهم میکند که ممکن است وقتی شی به زباله (Garbage) تبدیل شود روی آن فراخوانی شود. پیادهسازی Object برای finalize() هیچ کاری انجام نمیدهد. بازنویسی finalize() برای انجام پاکسازی مثل آزادسازی منابع انجام میشد.
متد finalize() ممکن است بهطور خودکار توسط سیستم فراخوانی شود، اما اینکه کی فراخوانی شود، یا حتی اینکه اصلاً فراخوانی شود یا نه، نامعلوم است. بنابراین نباید دیگر روی این متد برای پاکسازی خودکار منابع حساب کنید. مثلاً اگر File Descriptorها را بعد از انجام I/O نبندید و انتظار داشته باشید finalize() آنها را برای شما ببندد، ممکن است File Descriptorها تمام شوند.
از جاوا SE 9 متد finalize() Deprecated شده و از جاوا SE 18، Deprecated for Removal شده است. در زمانی نامعلوم، دیگر فراخوانی نخواهد شد. بازنویسی این متد اکنون اکیداً توصیه نمیشود. اگر نیاز دارید منابعی را پاکسازی کنید، میتوانید با پیادهسازی Interface AutoCloseable این کار را انجام دهید. این موضوع بهطور مفصل در بخش Java I/O پوشش داده شده است.
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://dev.java/learn/