97. آیا شرایط تعریف مجدد توافق هنگام تعریف مجدد Equals اعمال می شود؟
متد ()quals overridden باید با شرایط (قوانین) زیر مطابقت داشته باشد:-
انعکاسی - برای هر مقدار x، عبارتی مانند x.equals(x) همیشه باید true باشد (وقتی x != null ).
-
تقارن - برای هر مقدار x و y، یک عبارت به شکل x.equals(y) باید فقط در صورتی که y.equals(x) true را برگرداند .
-
گذر - برای هر مقدار x ، y و z ، اگر x.equals(y) true و y.equals(z) نیز true را برگرداند ، x.equals(z) باید true را برگرداند .
-
سازگاری - برای هر مقدار x و y، یک فراخوانی مکرر به x.equals(y) همیشه مقدار فراخوانی قبلی را به این متد برمی گرداند، مشروط بر اینکه فیلدهای مورد استفاده برای مقایسه این دو شی بین فراخوانی ها تغییر نکرده باشند. .
-
مقایسه null - برای هر مقدار x، فراخوانی x.equals(null) false را برمی گرداند .
98. اگر Equals و HashCode را لغو نکنید، چه اتفاقی میافتد؟
در این مورد، hashCode() عددی را برمیگرداند که بر اساس مکان حافظه که شی داده شده در آن ذخیره میشود، ایجاد شده است. به این معنی که دو شی با فیلدهای دقیقاً یکسان، هنگام فراخوانی یک hashCode() غیر رد شده ، مقادیر متفاوتی دریافت می کنند (به هر حال، آنها در مکان های مختلف حافظه ذخیره می شوند). unoverridden () quals مراجع را با هم مقایسه می کند تا ببیند آیا آنها به یک شی اشاره می کنند یا نه. یعنی مقایسه از طریق == انجام می شود و در مورد اشیاء با فیلدهای یکسان همیشه false بر می گردد . درست فقط زمانی خواهد بود که ارجاعات را به یک شیء مقایسه کنید. گاهی اوقات منطقی در عدم غلبه بر این روش ها وجود دارد. به عنوان مثال، شما می خواهید همه اشیاء یک کلاس خاص منحصر به فرد باشند و نادیده گرفتن این متدها فقط منطق منحصر به فرد بودن را از بین می برد. نکته اصلی این است که تفاوت های ظریف روش های نادیده گرفته شده و غیر رد شده را درک کنید و بسته به موقعیت از هر دو رویکرد استفاده کنید.99. چرا تقارن فقط در صورتی درست است که x.برابر (y) درست برگرداند؟
یه سوال کمی عجیب اگر جسم الف برابر با شیء B باشد، شیء B برابر با شیء A است. این یک منطق ساده است.100. برخورد در HashCode چیست؟ باید باهاش چکار کنم؟
برخورد هش کد وضعیتی است که در آن دو شی متفاوت دارای مقدار هش کد یکسان هستند . چه طور ممکنه؟ واقعیت این است که کد هش به نوع Integer نگاشت شده است ، که به نوبه خود دارای محدوده ای از -2147483648 تا 2147483647 است، یعنی تقریباً 4 میلیارد عدد صحیح مختلف. این محدوده بسیار زیاد است، با این حال، بی نهایت نیست. بنابراین، شرایط زمانی ممکن است که دو شی کاملاً متفاوت دارای کد هش یکسان باشند. این بسیار بعید است، اما ممکن است. یک تابع هش ضعیف همچنین می تواند فرکانس کدهای هش یکسان را افزایش دهد، که به عنوان مثال، اعداد را در یک محدوده کوچک برمی گرداند، که احتمال برخورد را افزایش می دهد. برای مبارزه با برخورد، باید روش hashCode را به خوبی پیاده سازی کنید تا گسترش مقادیر حداکثر و احتمال تکرار مقادیر حداقل باشد.101. اگر عنصری که در قرارداد HashCode شرکت می کند مقدار خود را تغییر دهد چه اتفاقی می افتد؟
اگر عنصری که در محاسبه کد هش دخیل است تغییر کرده باشد، کد هش خود شی تغییر خواهد کرد (اگر عملکرد هش خوب باشد). بنابراین، در HashMap توصیه می شود از اشیاء تغییرناپذیر (غیر قابل تغییر) به عنوان کلید استفاده کنید، زیرا حالت داخلی (فیلدها) آنها پس از ایجاد قابل تغییر نیست. بر این اساس، کد هش آنها نیز پس از ایجاد تبدیل نمی شود. اگر از یک شیء قابل تغییر به عنوان کلید استفاده می کنید، با تغییر فیلدهای این شیء، کد هش آن تغییر می کند و در نتیجه می توانید این جفت را در HashMap گم کنید . از این گذشته، برای کد هش اصلی در سطلی ذخیره می شود و پس از تغییر آن، در سطل دیگری جستجو می شود.102. متدهای Equals و HashCode را برای کلاس Student بنویسید که از نام رشته و فیلدهای int age تشکیل شده است.
public class Student {
int age;
String name;
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || this.getClass() != o.getClass()) {
return false;
}
final Student student = (Student) o;
if (this.age != student.age) {
return false;
}
return this.name != null ? this.name.equals(student.name) : student.name == null;
}
@Override
public int hashCode() {
int result = this.age;
result = 31 * result + (this.name != null ? this.name.hashCode() : 0);
return result;
}
}
برابر:
-
ابتدا لینک ها را مستقیماً با هم مقایسه می کنیم، زیرا اگر لینک ها به یک شیء باشند، ادامه بررسی چه فایده ای دارد؟ به هر حال همه چیز درست خواهد بود .
-
بررسی null و مطابقت انواع کلاس، زیرا اگر یک شی آرگومان null یا نوع دیگری باشد، به این معنی است که اشیاء برابر نیستند - false .
-
فرستادن شیء آرگومان به یک نوع (در صورتی که شیء از نوع والد باشد).
-
مقایسه یک فیلد کلاس ابتدایی (بالاخره، مقایسه از طریق =! برای آن کافی است )، اگر فیلد برابر نباشد - false .
-
بررسی یک فیلد غیر ابتدایی برای null و مساوی (در String متد لغو می شود و به درستی با هم مقایسه می شود)، اگر هر دو فیلد تهی یا مساوی باشند ، چک به پایان می رسد و متد true را برمی گرداند .
-
تنظیم مقدار کد هش اولیه روی سن اولیه شی .
-
ضرب کد هش فعلی در 31 (برای گسترش بیشتر) و اضافه کردن کد هش یک فیلد رشته غیر ابتدایی (اگر تهی نباشد).
-
برگرداندن نتیجه.
-
در نتیجه لغو این کد هش، اشیاء با همان نام و مقادیر int همیشه همان مقدار را برمیگردانند.
103. تفاوت بین استفاده از if (obj instanceof Student) و if (getClass() == obj.getClass()) چیست؟
بیایید ببینیم هر رویکرد چه کاری انجام می دهد:-
instanceof بررسی می کند که آیا مرجع شی در سمت چپ نمونه ای از نوع سمت راست است یا زیرگروهی از آن.
-
getClass() == ... هویت نوع را بررسی می کند.
104. توضیح مختصری از متد ()clone ارائه دهید.
Clone() متدی از کلاس Object است که هدف آن ایجاد و برگرداندن یک کلون از شی فعلی (یک کپی از شی فعلی) است. برای استفاده از آن، باید رابط نشانگر Cloneable را پیاده سازی کنید :Student implements Cloneable
و خود متد ()clone را لغو کنید :
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
از این گذشته، در کلاس Object محافظت شده است، یعنی فقط در خود کلاس Student قابل مشاهده است ، اما برای کلاس ها از خارج قابل مشاهده نیست.
105. ویژگی متد clone() که با فیلدهای یک شی از نوع مرجع کار می کند چیست؟
هنگام شبیه سازی اشیاء، فقط مقادیر اولیه و مقدار ارجاعات شیء کپی می شوند. این بدان معناست که اگر یک شی پیوندی به یک شی دیگر در فیلد داخلی خود داشته باشد، فقط این پیوند کلون می شود، اما خود این شیء دیگر کلون نمی شود. در واقع این همان چیزی است که آنها شبیه سازی سطحی می نامند. خوب، اگر نیاز به شبیه سازی کامل با شبیه سازی همه اشیاء تو در تو داشته باشید، چه؟ چگونه می توان مطمئن شد که اینها کپی پیوندها نیستند، بلکه کلون های کامل اشیاء با سایر سلول های حافظه اشغال شده در پشته هستند؟ در واقع، همه چیز بسیار ساده است - برای این کار باید متد clone() را در هر کلاس از این اشیاء داخلی نادیده بگیرید و یک رابط نشانگر اضافه کنید - Cloneable . سپس این ارجاع به اشیا کپی نمی شود، بلکه خود اشیا کپی می شوند، زیرا اکنون آنها نیز توانایی کپی کردن خود را دارند.استثناها
106. تفاوت بین خطا و استثنا چیست؟
هم استثناها و هم خطاها زیر کلاس های کلاس Throwable هستند . با این حال، آنها تفاوت های خود را دارند. خطا نشان دهنده مشکلی است که عمدتاً به دلیل منابع ناکافی سیستم رخ می دهد. و برنامه ما نباید این نوع مشکلات را شناسایی کند. برخی از نمونههای خطا عبارتند از خرابی سیستم و خطای کمبود حافظه. خطاها بیشتر در زمان اجرا رخ می دهند زیرا از نوع بررسی نشده هستند. استثناها مشکلاتی هستند که می توانند در زمان اجرا و در زمان کامپایل رخ دهند. معمولاً این اتفاق در کدهای نوشته شده توسط توسعه دهندگان رخ می دهد. یعنی استثناها بیشتر قابل پیش بینی هستند و بیشتر به ما به عنوان توسعه دهندگان وابسته هستند. در عین حال، خطاها تصادفی تر و مستقل تر از ما هستند، اما بیشتر به مشکلات مربوط به خود سیستمی که برنامه ما در آن اجرا می شود بستگی دارد.107. چه فرقی بین چک شده و تیک نشده، استثنا، پرتاب، پرتاب است.
همانطور که قبلاً گفتم، یک استثنا خطایی در حین اجرای برنامه و در حین کامپایل است که در کد نوشته شده توسط توسعه دهنده (به دلیل شرایط غیرعادی) رخ داده است. Checked نوعی استثنا است که همیشه باید با استفاده از مکانیسم try-catch مدیریت شود یا به روشهای بالا پرتاب شود. Throws در هدر متد برای نشان دادن استثناهای احتمالی پرتاب شده توسط متد استفاده می شود. یعنی، این مکانیسمی برای "پرتاب" استثناها به روش های بالا است. بدون علامت نوعی استثنا است که نیازی به رسیدگی ندارد و معمولا کمتر قابل پیش بینی است و احتمال وقوع آن کمتر است. با این حال، آنها همچنین می توانند در صورت تمایل پردازش شوند. پرتاب هنگام پرتاب یک استثنا به صورت دستی استفاده می شود، به عنوان مثال:throw new Exception();
108. سلسله مراتب استثناها چگونه است؟
سلسله مراتب استثناها بسیار بزرگ و گسترده است، حتی بسیار گسترده است که نمی توان همه چیز را در اینجا در مورد آن توضیح داد. بنابراین، ما فقط پیوندهای کلیدی آن را در نظر می گیریم: در اینجا در بالای سلسله مراتب، کلاس - Throwable - یک کلاس کلی، جد سلسله مراتب استثنا را می بینیم، که به نوبه خود به تقسیم می شود:- خطا - خطاهای مهم و غیرقابل بررسی.
- استثنا - استثنائات بررسی شده است.
109. استثناء تیک زده و تیک نشده چیست؟
همانطور که قبلا گفتم:-
علامت زده شد - استثناهایی که باید به نحوی آنها را مدیریت کنید، یعنی یا آنها را در یک بلوک try-catch پردازش کنید ، یا آنها را به روش بالا "فرورو" کنید. برای انجام این کار، در امضای متد، پس از فهرست کردن آرگومان های متد، باید از کلیدواژه trows <exception type> استفاده کنید که به کاربران متد نشان می دهد که متد می تواند این استثنا را پرتاب کند (چیزی شبیه هشدار) و مسئولیت رسیدگی به استثنا به کاربران این روش.
-
بدون علامت - استثناهایی که نیازی به رسیدگی ندارند، زیرا در زمان کامپایل بررسی نمی شوند و به عنوان یک قاعده، غیرقابل پیش بینی تر هستند. یعنی تفاوت اصلی با checked این است که برای آنها این مکانیسم های try-catch یا پرتاب یکسان عمل می کنند، اما اجباری نیستند.
101. مثالی از رهگیری و مدیریت یک استثنا در بلوک try-catch یک متد بنویسید.
try{ // начало блока перехвата
throw new Exception(); // ручной бросок исключения
} catch (Exception e) { // данное исключение и его потомки будут перехватываться
System.out.println("Упс, что-то пошло не так =("); // вывод некоторого исключения в консоль
}
102. مثالی از گرفتن و رسیدگی به یک استثنا با استفاده از استثناهای خود بنویسید
ابتدا، بیایید کلاس استثنای خودمان را بنویسیم، که از Exception به ارث میبرد و سازنده آن را با یک پیام خطا لغو میکند:public class CustomException extends Exception {
public CustomException(final String message) {
super(message);
}
}
خوب، سپس آن را به صورت دستی پرتاب می کنیم و مانند سوال قبلی آن را قطع می کنیم:
try{
throw new CustomException("Упс, что-то пошло не так =(");
} catch (CustomException e) {
System.out.println(e.getMessage());
}
و دوباره وقتی آن را اجرا می کنید، خروجی زیر را به کنسول دریافت خواهید کرد:
GO TO FULL VERSION