در دو مقاله قبلی، چند سوال مهم که بیشتر در مصاحبه ها از شما پرسیده می شود را مورد بحث قرار دادیم. وقت آن است که ادامه دهید و به بقیه سؤالات نگاه کنید.
کپی عمیق و کپی کم عمق
یک کپی دقیق از نسخه اصلی شبیه سازی آن است. در جاوا، این به معنای توانایی ایجاد یک شی با ساختاری مشابه با شی اصلی است. روشclone()
این قابلیت را فراهم می کند. کپی کردن کم عمق تا حد امکان اطلاعات کمتری را به همراه دارد. به طور پیش فرض، شبیه سازی در جاوا سطحی است، یعنی. Object class
از ساختار کلاسی که کپی می کند اطلاعی ندارد. هنگام شبیه سازی، JVM کارهای زیر را انجام می دهد:
- اگر یک کلاس فقط دارای اعضایی از انواع اولیه باشد، یک کپی کاملاً جدید از شی ایجاد می شود و یک مرجع به آن شی بازگردانده می شود.
- اگر یک کلاس نه تنها شامل اعضای انواع اولیه، بلکه اعضای هر نوع کلاس دیگر باشد، ارجاعات به اشیاء این کلاس ها کپی می شوند. بنابراین، هر دو شی مراجع یکسان خواهند داشت.
- نیازی به کپی کردن داده های اولیه به طور جداگانه نیست.
- تمام کلاس های عضو در کلاس اصلی باید از شبیه سازی پشتیبانی کنند. برای هر یک از اعضای کلاس، باید
super.clone()
زمانی فراخوانی شود که متد لغو شودclone()
. - اگر هر یک از اعضای یک کلاس از شبیه سازی پشتیبانی نمی کند، در متد clone، باید یک نمونه جدید از آن کلاس ایجاد کنید و هر یک از اعضای آن را با تمام ویژگی ها در یک شی کلاس جدید کپی کنید.
همگام سازی چیست؟ قفل در سطح شی و قفل در سطح کلاس؟
همگام سازی به چند رشته ای اشاره دارد. یک بلوک همگام شده از کد را فقط می توان توسط یک رشته در یک زمان اجرا کرد. جاوا به شما اجازه می دهد تا چندین رشته را به طور همزمان پردازش کنید. این ممکن است منجر به این شود که دو یا چند رشته بخواهند به یک فیلد دسترسی داشته باشند. همگام سازی کمک می کند تا از خطاهای حافظه که هنگام استفاده نادرست از منابع حافظه رخ می دهد جلوگیری شود. هنگامی که یک روش به عنوان همگام اعلام می شود، موضوع مانیتور خود را نگه می دارد. اگر رشته دیگری در این زمان سعی کند به یک روش همگام شده دسترسی پیدا کند، رشته مسدود شده و منتظر می ماند تا مانیتور آزاد شود. همگام سازی در جاوا با کلمه کلیدی همگام شده ویژه انجام می شود . شما می توانید بلوک ها یا متدهای جداگانه را در کلاس خود از این طریق علامت گذاری کنید. کلمه کلیدی همگام سازی شده را نمی توان همراه با متغیرها یا ویژگی های کلاس استفاده کرد. قفل کردن سطح شی مکانیزمی است که می خواهید یک متد غیر ایستا یا بلوک کد غیر ایستا را همگام کنید تا فقط یک رشته بتواند بلوک کد را در یک نمونه معین از کلاس اجرا کند. این باید همیشه انجام شود تا رشته نمونه کلاس ایمن باشد. قفل کردن در سطح کلاس از ورود چندین رشته به یک بلوک همگامسازی شده برای همه نمونههای موجود کلاس جلوگیری میکند. برای مثال، اگر 100 نمونه از کلاس DemoClass وجود داشته باشد، آنگاه تنها 1 رشته میتواند ()demoMethod را با استفاده از یکی از متغیرها در یک زمان معین اجرا کند. این باید همیشه برای اطمینان از ایمنی رزوه استاتیک انجام شود. در اینجا درباره همگام سازی بیشتر بیاموزید.تفاوت بین sleep() و wait() چیست؟
Sleep()
روشی است که برای به تاخیر انداختن فرآیند برای چند ثانیه استفاده می شود. در مورد wait()
، رشته در حالت انتظار است تا زمانی که متد notify()
یا را فراخوانی کنیم notifyAll()
. تفاوت اصلی این است که wait()
قفل مانیتور را آزاد می کند در حالی که sleep()
قفل را باز نمی کند. Wait()
برای برنامه های چند رشته ای استفاده می شود، sleep()
به سادگی برای توقف اجرای رشته استفاده می شود. Thread.sleep()
رشته فعلی را برای مدت زمان معینی در وضعیت "غیر قابل اجرا" قرار می دهد. thread وضعیت مانیتور را که قبل از فراخوانی این روش بود ذخیره می کند. اگر رشته دیگری تماس بگیرد t.interrupt()
، رشته ای که "خواب شد" بیدار می شود. توجه داشته باشید که این sleep()
یک روش ایستا است، به این معنی که همیشه روی رشته فعلی (متد که روش را اجرا می کند sleep()
) تأثیر می گذارد. یک اشتباه رایج فراخوانی t.sleep()
جایی است که t
موضوع دیگری وجود دارد. حتی زمانی که thread فعلی که متد را فراخوانی کرده است یک نخ sleep()
نباشد t
. Object.wait()
thread فعلی را برای مدتی به حالت "Not Runnable" می فرستد، درست مانند sleep()
، اما با مقداری تفاوت. Wait()
بر روی یک شیء فراخوانی می شود، نه یک رشته. ما این شی را "شیء قفل" می نامیم. قبل از فراخوانی lock.wait()
، موضوع فعلی باید با "شیء قفل" همگام شود. wait()
پس از آن، این قفل را آزاد می کند و موضوع را به "لیست انتظار" مرتبط با این قفل اضافه می کند. بعداً، رشته دیگری می تواند با همان شی قفل همگام شود و lock.notify()
. این روش موضوع اصلی را که هنوز در انتظار است، "بیدار می کند". در اصل، wait()
/ را notify()
می توان با sleep()
/ مقایسه کرد interrupt()
، فقط رشته فعال نیازی به اشاره گر مستقیم به رشته خواب ندارد، فقط باید شی قفل مشترک را بشناسد. تفاوت تفصیلی را اینجا بخوانید.
آیا می توان null را به یک متغیر مرجع اختصاص داد؟
نه نمی توانی. در جاوا، سمت چپ عملگر انتساب باید یک متغیر باشد. "This" یک کلمه کلیدی ویژه است که همیشه نمونه فعلی کلاس را نشان می دهد. این فقط هر متغیری نیست. به همین ترتیب، null را نمی توان با استفاده از کلمه کلیدی “super” یا هر کلمه کلیدی مشابه دیگری به یک متغیر اختصاص داد.تفاوت بین && و & چیست؟
&
- به صورت بیتی و &&
- به صورت منطقی.
&
هر دو طرف عملیات را ارزیابی می کند.&&
سمت چپ عملیات را ارزیابی می کند. اگر درست باشد، به ارزیابی سمت راست ادامه می دهد.
چگونه می توان متدهای برابر () و ()hachCode را نادیده گرفت؟
hashCode()
و equals()
متدها در کلاس تعریف می شوند Object
که کلاس والد برای اشیاء جاوا است. به همین دلیل، تمام اشیاء جاوا پیاده سازی پیش فرض را برای متدها به ارث می برند. این روش hashCode()
برای به دست آوردن یک عدد صحیح منحصر به فرد برای یک شی معین استفاده می شود. این عدد صحیح برای تعیین مکان یک شی در زمانی که آن شی باید ذخیره شود، به عنوان مثال در HashTable
. به طور پیشفرض، نمایشی از آدرس محل حافظه که شی ذخیره میشود را hashCode()
برمیگرداند . integer
این روش equls()
همانطور که از نامش پیداست برای آزمایش اینکه آیا دو شیء برابر هستند یا خیر استفاده می شود. پیاده سازی پیش فرض مراجع اشیا را بررسی می کند تا ببیند که آیا آنها برابر هستند یا خیر. در زیر دستورالعمل های مهم برای بارگذاری مجدد این روش ها وجود دارد:
- همیشه هنگام تولید
hashCode()
وequals()
; - تقارن. آن ها
x
اگر مقدار true را برای برخی از اشیاء برگرداندy
x.equals(y)
،y.equals(x)
باید true را برگرداند. - انعکاس پذیری. برای هر شیء
x
x.equals(x)
باید true باشد. - ثبات. اگر اطلاعات مورد استفاده در مقایسه ها تغییر نکند، برای هر شی
x
و همان چیزی را برمی گرداند.y
x.equals(y)
- گذرا. برای هر شیء
x
،y
وz
، اگرx.equals(y)
true را برگرداند وy.equals(z)
true را برگرداند،x.equals(z)
باید true را برگرداند. - هرگاه متدی در حین اجرای برنامه بر روی همان شیء فراخوانی شود، باید همان عدد را برگرداند مگر اینکه اطلاعات استفاده شده تغییر کند.
hashCode
می تواند مقادیر متفاوتی را برای اشیاء یکسان در نمونه های کاربردی مختلف برگرداند. - اگر دو شیء برابر باشند، با توجه به
equals
، آنگاهhashCode
باید مقادیر یکسانی را برگردانند. - شرط مخالف اختیاری است. دو شی نابرابر می توانند یک کد هش را برگردانند. با این حال، برای بهبود عملکرد، بهتر است که اشیاء مختلف کدهای متفاوتی را برگردانند.
در مورد اصلاح کننده های دسترسی به ما بگویید
کلاسها، فیلدها، سازندهها و متدهای جاوا میتوانند یکی از چهار تغییر دهنده دسترسی مختلف را داشته باشند: خصوصی اگر متد یا متغیری خصوصی علامتگذاری شده باشد ، تنها کدهای درون همان کلاس میتوانند به متغیر دسترسی داشته باشند یا متد را فراخوانی کنند. کدهای درون کلاسهای فرعی نمیتوانند به یک متغیر یا متد دسترسی داشته باشند و همچنین نمیتوانند از هر کلاس دیگری به آن دسترسی داشته باشند. اصلاح کننده دسترسی خصوصی اغلب برای سازنده ها، متدها و متغیرها استفاده می شود. پیش فرض اصلاح کننده دسترسی پیش فرض در صورتی اعلام می شود که اصلاح کننده اصلاً مشخص نشده باشد. این اصلاح کننده به این معنی است که دسترسی به فیلدها، سازنده ها و متدهای یک کلاس معین را می توان با کدهای داخل خود کلاس، کدهای داخل کلاس ها در همان بسته به دست آورد. اگر زیر کلاس ها به عنوان پیش فرض اعلام شوند، نمی توانند به متدها و متغیرهای عضو یک سوپرکلاس دسترسی داشته باشند ، مگر اینکه کلاس فرعی در همان بسته سوپرکلاس باشد. محافظت شده اصلاحکننده محافظتشده مانند پیشفرض کار میکند ، با این تفاوت که کلاسهای فرعی میتوانند به متدها و متغیرهای محافظتشده سوپرکلاس نیز دسترسی داشته باشند. این عبارت درست است حتی اگر زیر کلاس در همان بسته سوپرکلاس نباشد. public اصلاح کننده دسترسی عمومی به این معنی است که همه کدها می توانند به کلاس، متغیرها، سازنده ها یا متدهای آن دسترسی داشته باشند، صرف نظر از اینکه آن کد در کجا قرار دارد.زباله جمع کن چیست؟ میشه باهاش تماس بگیریم؟
جمع آوری زباله یکی از ویژگی های مدیریت خودکار حافظه در بسیاری از زبان های برنامه نویسی مدرن مانند جاوا و زبان های موجود در NET.Framework است. زبان هایی که از جمع آوری زباله استفاده می کنند اغلب جمع آوری زباله را در یک ماشین مجازی مانند JVM تفسیر می کنند. جمع آوری زباله دو هدف دارد: هر حافظه استفاده نشده ای باید آزاد شود و اگر برنامه همچنان از آن استفاده می کند، نباید حافظه آزاد شود. آیا می توانید جمع آوری زباله را به صورت دستی اجرا کنید؟ خیر،System.gc()
تا حد امکان به شما دسترسی می دهد. بهترین گزینه این است که متد را فراخوانی کنید System.gc()
، که به جمع کننده زباله نشان می دهد که باید اجرا شود. هیچ راهی برای اجرای فوری آن وجود ندارد زیرا زباله جمع کن غیر قطعی است. علاوه بر این، با توجه به مستندات، OutOfMemoryError
اگر ماشین مجازی پس از جمعآوری کامل زباله نتواند حافظه را آزاد کند، ارسال نخواهد شد. در اینجا درباره زباله جمع کن بیشتر بدانید.
کلمه کلیدی بومی به چه معناست؟ به تفصیل توضیح دهید
کلمه کلیدی بومی برای نشان دادن اینکه این روش در زبان برنامه نویسی غیر از فایل جاوا پیاده سازی شده است استفاده می شود. روش های بومی در گذشته مورد استفاده قرار می گرفته است. در نسخه های فعلی جاوا این مورد کمتر مورد نیاز است. در حال حاضر، روشهای بومی زمانی مورد نیاز است که:- شما باید با کتابخانه ای از جاوا که به زبان دیگری نوشته شده است تماس بگیرید.
- شما نیاز به دسترسی به منابع سیستم یا سخت افزاری دارید که فقط با استفاده از زبان دیگری (معمولاً C) قابل دسترسی هستند. در واقع، بسیاری از توابع سیستمی که با رایانه واقعی در تعامل هستند (مانند دیسک ها یا داده های شبکه) فقط می توانند با روش بومی فراخوانی شوند.
- JNI/JNA میتواند JVM را بیثبات کند، به خصوص اگر بخواهید کاری پیچیده انجام دهید. اگر متد بومی شما کار اشتباهی انجام دهد، احتمال خرابی JVM وجود دارد. همچنین، اگر متد بومی شما از چندین رشته فراخوانی شود، ممکن است اتفاقات بدی بیفتد. و غیره.
- اشکال زدایی یک برنامه با کد بومی دشوارتر است .
- کد بومی نیاز به ساخت فریمورک های جداگانه دارد که می تواند مشکلاتی را در انتقال به پلتفرم های دیگر ایجاد کند.
سریال سازی چیست؟
در علم کامپیوتر، در زمینه ذخیره سازی و انتقال داده، سریال سازی فرآیند ترجمه یک ساختار داده یا وضعیت یک شی به قالبی است که می تواند بعداً در یک محیط محاسباتی دیگر ذخیره و بازیابی شود. پس از دریافت یک سری بیت، آنها با توجه به فرمت سریال سازی مجدداً محاسبه می شوند و می توان از آنها برای ایجاد یک کلون معنایی یکسان از شی اصلی استفاده کرد. جاوا سریال سازی خودکار را ارائه می دهد که برای پیاده سازی رابط به شی نیاز داردjava.io.Serializable
. پیاده سازی رابط کلاس را به عنوان "Serializable" علامت گذاری می کند. رابط java.io.Serializable متدهای سریالسازی ندارد، اما کلاس سریالسازی میتواند بهطور اختیاری روشهایی را تعریف کند که به عنوان بخشی از فرآیند سریالسازی/دیسریسازی فراخوانی میشوند. هنگام ایجاد تغییرات در کلاسها، باید در نظر بگیرید که کدام یک با سریالسازی سازگار هستند و نمیشوند. شما می توانید دستورالعمل های کامل را در اینجا بخوانید. من مهمترین نکات را عرض می کنم: تغییرات ناسازگار:
- حذف یک فیلد؛
- یک کلاس را در سلسله مراتب به بالا یا پایین ببرید.
- تغییر یک میدان غیر ساکن به ایستا یا غیر گذرا به گذرا.
- تغییر نوع داده اولیه اعلام شده؛
- تغییر روش
WriteObject
یاReadObject
به گونه ای که دیگر فیلدها را به طور پیش فرض نمی نویسند یا نمی خوانند. - تغییر کلاس
Serializable
بهExternalizable
یا برعکس؛ - تغییر یک کلاس enum به غیر enum یا بالعکس.
- حذف
Serializable
یاExternalizable
؛ - افزودن
writeReplace
متدreadResolve
به کلاس
- افزودن فیلدها؛
- اضافه کردن/حذف کلاس ها؛
- افزودن روش ها
WriteObject/ReadObject
[روش هاdefaultReadObject
یاdefaultWriteObject
باید در ابتدا فراخوانی شوند]. - روش های حذف
WriteObject/ReadObject
؛ - اضافه
java.io.Serializable
_ - تغییر دسترسی میدانی؛
- تغییر یک میدان استاتیک به غیر ایستا یا گذرا به غیر گذرا .
GO TO FULL VERSION