سلام! امروز در مورد عملگر instanceof صحبت خواهیم کرد، نمونه هایی از استفاده از آن را بررسی خواهیم کرد و برخی از نکات مربوط به عملکرد آن را لمس خواهیم کرد :) در سطوح اولیه JavaRush، قبلاً با این عملگر مواجه شده اید. آیا به خاطر دارید که چرا به آن نیاز است؟ اگر نه، مهم نیست، بیایید با هم به یاد بیاوریم. عملگر instanceof برای بررسی اینکه آیا شیء ارجاع شده توسط متغیر X از کلاس Y ساخته شده است یا خیر لازم است. چرا به این موضوع برگشتیم؟ اول از همه به این دلیل که اکنون به خوبی با مکانیسم وراثت در جاوا و سایر اصول OOP آشنا هستید. موضوع instanceof بسیار واضح تر خواهد بود و ما به موارد استفاده پیشرفته تر نگاه خواهیم کرد. برو! احتمالاً به یاد دارید که عملگر instanceof در صورت درست بودن تست، true را برمیگرداند، یا اگر نتیجه نادرست بود، false را برمیگرداند . در نتیجه، اغلب در انواع مختلف شرایط آزمایش یافت می شود (
if…else
). بیایید با مثال های ساده تر شروع کنیم:
public class Main {
public static void main(String[] args) {
Integer x = new Integer(22);
System.out.println(x instanceof Integer);
}
}
به نظر شما خروجی کنسول چه خواهد بود؟ خب، اینجا واضح است :) شی х
یک عدد صحیح است، بنابراین نتیجه درست خواهد بود . خروجی کنسول: true بیایید سعی کنیم بررسی کنیم که آیا به عنوان مثال به String تعلق دارد یا خیر:
public class Main {
public static void main(String[] args) {
Integer x = new Integer(22);
System.out.println(x instanceof String);// error!
}
}
ما یک خطا دریافت کردیم. و توجه کنید: کامپایلر آن را حتی قبل از اجرای کد صادر کرده است! او بلافاصله متوجه شد که Integer و String نمی توانند به طور خودکار به یکدیگر تبدیل شوند و روابط ارثی ندارند. بنابراین، یک شی کلاس Integer از رشته ایجاد نخواهد شد. این راحت است و به جلوگیری از خطاهای عجیب و غریب در حین اجرای برنامه کمک می کند، بنابراین کامپایلر در اینجا به ما کمک کرد :) حالا بیایید سعی کنیم به نمونه های پیچیده تر نگاه کنیم. از آنجایی که به وراثت اشاره کردیم، بیایید با این سیستم کلاس کوچک کار کنیم:
public class Animal {
}
public class Cat extends Animal {
}
public class MaineCoon extends Cat {
}
ما قبلاً می دانیم که وقتی بررسی می کنیم که آیا یک شی به یک کلاس در یک موقعیت عادی تعلق دارد یا خیر، instanceof چگونه رفتار می کند، اما اگر یک رابطه والد-فرزند را در اینجا اضافه کنیم چه اتفاقی می افتد؟ به عنوان مثال، به نظر شما چک زیر چه چیزی را تولید می کند:
public class Main {
public static void main(String[] args) {
Cat cat = new Cat();
System.out.println(cat instanceof Animal);
System.out.println(cat instanceof MaineCoon);
}
}
خروجی: true false سوال اصلی که باید به آن پاسخ داده شود این است که چگونه instanceof مفهوم "یک شی ایجاد شده بر اساس یک کلاس" را رمزگشایی می کند؟ در نتیجه، ما آن را دریافت کردیم Сat instanceof Animal == true
، اما می توان با چنین فرمولی ایراد گرفت. چرا این شی Cat
بر اساس کلاس ایجاد شده است Animal
؟ آیا فقط بر اساس کلاس خودش ایجاد نشده است؟ پاسخ بسیار ساده است و شاید قبلاً آن را فهمیده باشید. هنگام ایجاد یک شی، ترتیب فراخوانی سازنده ها و مقداردهی اولیه متغیرها را به خاطر بسپارید. قبلاً در مقاله سازنده کلاس به این موضوع پرداخته ایم . در اینجا یک نمونه از آن سخنرانی آورده شده است:
public class Animal {
String brain = "The initial value of brain in the Animal class";
String heart = "The initial value of heart in the Animal class";
public static int animalCount = 7700000;
public Animal(String brain, String heart) {
System.out.println("The constructor of the Animal base class is being executed");
System.out.println("Have the variables of the Animal class already been initialized?");
System.out.println("The current value of the static variable animalCount = " + animalCount);
System.out.println("Current value of brain in class Animal = " + this.brain);
System.out.println("Current value of heart in class Animal = " + this.heart);
this.brain = brain;
this.heart = heart;
System.out.println("Animal base class constructor completed!");
System.out.println("Current value of brain = " + this.brain);
System.out.println("Current value of heart = " + this.heart);
}
}
class Cat extends Animal {
String tail = "The initial value of tail in the Cat class";
static int catsCount = 37;
public Cat(String brain, String heart, String tail) {
super(brain, heart);
System.out.println("The constructor of the Cat class has started (the Animal constructor has already been executed)");
System.out.println("The current value of the static variable catsCount = " + catsCount);
System.out.println("Current value tail = " + this.tail);
this.tail = tail;
System.out.println("Current value tail = " + this.tail);
}
public static void main(String[] args) {
Cat cat = new Cat("Brain", "Heart", "Tail");
}
}
و اگر آن را در IDE اجرا کنید، خروجی کنسول به این صورت خواهد بود: سازنده کلاس پایه Animal در حال اجرا است آیا متغیرهای کلاس Animal قبلاً مقداردهی اولیه شده اند؟ مقدار فعلی متغیر استاتیک animalCount = 7700000 مقدار فعلی مغز در کلاس Animal = مقدار اولیه مغز در کلاس Animal مقدار فعلی قلب در کلاس Animal = مقدار اولیه قلب در کلاس Animal سازنده پایه کلاس Animal کار خود را به پایان رسانده است! مقدار فعلی مغز = مغز مقدار فعلی قلب = قلب سازنده کلاس Cat شروع به کار کرده است (سازنده Animal قبلاً اجرا شده است) مقدار فعلی متغیر ثابت catsCount = 37 مقدار فعلی دم = مقدار اولیه دم در کلاس گربه ارزش فعلی دم = دم الان به یاد دارید؟ :) سازنده کلاس پایه، اگر وجود داشته باشد، همیشه هنگام ایجاد هر شی، ابتدا فراخوانی می شود. Instanceof از این اصل پیروی می کند زمانی که سعی می کند تعیین کند آیا یک شی А
از یک کلاس ایجاد شده است یا خیر Б
. اگر سازنده کلاس پایه فراخوانی شود، دیگر شکی وجود ندارد. با بررسی دوم همه چیز ساده تر است:
System.out.println(cat instanceof MaineCoon);
سازنده MaineCoon
هنگام ایجاد فراخوانی نشد Cat
که منطقی است. به هر حال، MaineCoon
او یک نسل است Cat
، نه یک اجداد. اما Cat
این یک الگو برای. خوب، این به نظر واضح است. اگر این کار را انجام دهیم چه اتفاقی می افتد:
public class Main {
public static void main(String[] args) {
Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
}
}
هوم ... این پیچیده تر است. بیایید سعی کنیم استدلال کنیم. ما یک متغیر از نوع داریم Cat
و یک شی از نوع را به آن اختصاص داده ایم MaineCoon
. به هر حال، چرا این حتی کار می کند؟ آیا انجام این کار ممکن است؟ می توان. به هر حال، هر مین کون یک گربه است. اگر کاملاً واضح نیست، مثال را با پسوندهای نوع اولیه به خاطر بسپارید:
public class Main {
public static void main(String[] args) {
long x = 1024;
}
}
عدد 1024 کوتاه است : به راحتی در متغیر long قرار می گیرد ، زیرا تعداد بایت ها برای آن کافی است (مثال عروسک های تودرتو را به خاطر دارید؟). یک شی فرزند همیشه می تواند به یک متغیر اجداد اختصاص داده شود. فقط این را فعلا به خاطر بسپارید و در سخنرانی های بعدی این روند را بیشتر تحلیل خواهیم کرد. بنابراین مثال ما چه چیزی تولید خواهد کرد؟
Cat cat = new MaineCoon();
System.out.println(cat instanceof Cat);
System.out.println(cat instanceof MaineCoon);
instanceof چه چیزی را بررسی می کند: متغیر کلاس ما Cat
یا شی کلاس ما MaineCoon
؟ در واقع، پاسخ به این سوال ساده است. فقط باید تعریف عملگر ما را دوباره بخوانید: عملگر instanceof برای بررسی اینکه آیا شیء ارجاع شده توسط متغیر X
بر اساس کلاسی ایجاد شده است یا خیر، مورد نیاز است Y
. عملگر instanceof مبدا یک شی را بررسی می کند نه یک متغیر. بنابراین، در مثال، هر دو بار در کنسول true نمایش داده می شود : ما یک شی از نوع داریم MaineCoon
. به طور طبیعی، آن را بر اساس کلاس ایجاد شده است MaineCoon
، اما همچنین بر اساس کلاس پدر بیش Cat
از حد!
GO TO FULL VERSION