CodeGym /وبلاگ جاوا /Random-FA /50 پرسش و پاسخ برتر مصاحبه شغلی برای Java Core. قسمت 1
John Squirrels
مرحله
San Francisco

50 پرسش و پاسخ برتر مصاحبه شغلی برای Java Core. قسمت 1

در گروه منتشر شد
سلام به همه خانم ها و آقایان مهندس نرم افزار! بیایید در مورد سوالات مصاحبه صحبت کنیم. در مورد آنچه که باید برای آن آماده شوید و آنچه باید بدانید. این زمان بسیار خوبی برای مرور یا مطالعه این نکات برای اولین بار است. 50 پرسش و پاسخ برتر مصاحبه شغلی برای Java Core.  قسمت 1 - 1 من با مجموعه نسبتاً گسترده ای از سؤالات متداول در مورد OOP، نحو جاوا، استثناهای جاوا، مجموعه ها و چند رشته ای به پایان رسیدم که برای راحتی کار به چندین بخش تقسیم می کنم. پوشاندن همه چیز به یکباره دشوار است، اما امیدوارم این مطالب پایه خوبی برای کسانی که آماده پیدا کردن اولین شغل خود به عنوان برنامه نویس هستند، فراهم کند. برای درک بهتر و حفظ، توصیه می کنم منابع دیگر را نیز بررسی کنید. شما می توانید با نزدیک شدن به یک مفهوم از چندین زاویه مختلف، درک عمیق تری از آن به دست آورید. مهم:ما فقط در مورد جاوا قبل از نسخه 8 صحبت خواهیم کرد. تمام نوآوری هایی که در نسخه های 9، 10، 11، 12 و 13 ارائه شده اند در اینجا در نظر گرفته نمی شوند. هر گونه ایده / نظر در مورد چگونگی بهبود پاسخ ها استقبال می شود . از خواندن خود لذت ببرید. بیا بریم!

مصاحبه جاوا: سوالاتی در مورد OOP

1. ویژگی های جاوا چیست؟

پاسخ:
  1. مفاهیم OOP:

    1. شی گرایی
    2. وراثت
    3. کپسوله سازی
    4. پلی مورفیسم
    5. انتزاع - مفهوم - برداشت
  2. Cross-platform: یک برنامه جاوا را می توان بر روی هر پلتفرمی بدون هیچ تغییری اجرا کرد. البته، این به یک JVM (ماشین مجازی جاوا) نصب شده نیاز دارد.

  3. عملکرد بالا: کامپایلر Just-In-Time (JIT) کارایی بالا را ممکن می کند. کامپایلر JIT بایت کد را به کد ماشین تبدیل می کند و سپس JVM اجرا را آغاز می کند.

  4. Multithreading: JVM یک رشته اجرا به نام main thread. یک برنامه نویس می تواند با استخراج از کلاس Thread یا پیاده سازی Runnableرابط، چندین رشته ایجاد کند.

2. ارث چیست؟

وراثت به این معنی است که یک کلاس می تواند کلاس دیگری را (با استفاده از کلمه کلیدی extensions ) به ارث ببرد. این بدان معنی است که می توانید از کد کلاسی که به ارث برده اید دوباره استفاده کنید. کلاس موجود به عنوان the شناخته می شود superclassو کلاس جدید ایجاد شده همان است subclass. مردم همچنین می گویند از اصطلاحات والدین و child.
public class Animal {
   private int age;
}

public class Dog extends Animal {

}
کجاست و هست . Animal_parentDogchild

3. کپسولاسیون چیست؟

این سوال اغلب در مصاحبه ها برای موقعیت های توسعه دهنده جاوا پرسیده می شود. کپسوله سازی با استفاده از اصلاح کننده های دسترسی، دریافت کننده ها و تنظیم کننده ها، اجرا را پنهان می کند. این کار به منظور جلوگیری از دسترسی خارجی در هر جایی که توسعه دهندگان فکر می کنند لازم است انجام می شود. یک مثال ساده از زندگی واقعی ماشین است. ما هیچ دسترسی مستقیمی به عملکرد موتور نداریم. تنها کاری که باید انجام دهیم این است که کلید را داخل موتور قرار داده و موتور را روشن کنیم. فرآیندهایی که در زیر کاپوت انجام می شود به ما مربوط نیست. علاوه بر این، اگر بخواهیم در فعالیت موتور دخالت کنیم، می تواند منجر به وضعیت غیرقابل پیش بینی و احتمالا آسیب رساندن به خودرو و در نتیجه آسیب بدنی شود. دقیقاً همین اتفاق در برنامه نویسی می افتد. این به خوبی در ویکی پدیا توضیح داده شده است . همچنین مقاله ای در مورد کپسوله سازی در CodeGym وجود دارد .

4. پلی مورفیسم چیست؟

Polymorphism توانایی یک برنامه برای برخورد با اشیاء با رابط یکسان به روشی یکسان، بدون اطلاعات در مورد نوع خاص شی است. همانطور که گفته می شود، "یک رابط - پیاده سازی های متعدد". با پلی مورفیسم، می توانید انواع مختلفی از اشیاء را بر اساس رفتارهای مشترک ترکیب و استفاده کنید. به عنوان مثال، ما یک کلاس Animal داریم که دارای دو نسل است: Dog و Cat. کلاس Animal عمومی دارای یک رفتار مشترک برای همه است، توانایی ایجاد صدا. زمانی که نیاز داریم هر چیزی را که کلاس Animal را به ارث می برد جمع آوری کنیم و متد «ساخت صدا» را اجرا کنیم، از قابلیت های چند شکلی استفاده می کنیم. در اینجا به نظر می رسد:
List<Animal> animals = Arrays.asList(new Cat(), new Dog(), new Cat());
animals.forEach(animal -> animal.makeSound());
به عبارت دیگر، پلی مورفیسم مفید است. و این در مورد روش های چند شکلی (بارگذاری بیش از حد) نیز صدق می کند. نحوه استفاده از پلی مورفیسم

سوالات مصاحبه در مورد نحو جاوا

5. سازنده در جاوا چیست؟

سازندگان دارای ویژگی های زیر هستند:
  1. هنگامی که یک شی جدید ایجاد می شود، برنامه از سازنده مناسب برای ایجاد آن استفاده می کند.
  2. سازنده مانند یک روش است. ویژگی های متمایز آن در این واقعیت نهفته است که هیچ مقدار بازگشتی (از جمله void) وجود ندارد و نام آن با نام کلاس یکسان است.
  3. اگر هیچ سازنده ای به طور صریح ایجاد نشود، یک سازنده خالی به طور خودکار ایجاد می شود.
  4. یک سازنده را می توان نادیده گرفت.
  5. اگر سازنده ای را با پارامترها اعلام کنید اما به یک سازنده بدون پارامتر نیز نیاز دارید، باید آن را جداگانه ایجاد کنید، زیرا به طور خودکار ایجاد نمی شود.

6. کدام دو کلاس Object را به ارث نمی برند؟

فریب سوالات ترفندی را نخورید - چنین کلاس هایی وجود ندارد. همه کلاس ها کلاس Object را به طور مستقیم یا از طریق اجداد به ارث می برند!

7. متغیر محلی چیست؟

این یکی دیگر از سوالات مصاحبه محبوب برای توسعه دهندگان جاوا است. متغیر محلی متغیری است که در داخل یک متد تعریف می شود و تا زمانی که متد در حال اجرا است وجود دارد. به محض پایان اجرا، متغیر محلی وجود ندارد. در اینجا برنامه ای وجود دارد که از یک متغیر محلی به نام helloMessage در متد main() استفاده می کند:
public static void main(String[] args) {
   String helloMessage;
   helloMessage = "Hello, World!";
   System.out.println(helloMessage);
}

8. متغیر نمونه چیست؟

متغیر نمونه، متغیری است که در یک کلاس اعلان می شود. تا زمانی که یک شی وجود دارد وجود دارد. به عنوان مثال، ما یک کلاس Bee داریم که دارای دو متغیر نمونه است - nectarLoad و maxNectarLoad:
public class Bee {

   /**
    * Current nectar load
    */
   private double nectarLoad;

   /**
    * Maximum nectar that can the bee can collect.
    */
   private double maxNectarLoad = 20.0;

  ...
}

9. اصلاح کننده های دسترسی چیست؟

اصلاح کننده های دسترسی مکانیزمی برای سفارشی کردن دسترسی به کلاس ها، متدها و متغیرها هستند. اصلاح کننده های زیر وجود دارند که به ترتیب افزایش دسترسی فهرست شده اند:
  1. private- این اصلاح کننده دسترسی روی متدها، فیلدها و سازنده ها استفاده می شود. دسترسی محدود به کلاسی است که در آن اعلان شده اند.
  2. package-private (default)- این سطح دسترسی پیش‌فرض برای کلاس‌ها است. دسترسی محدود به بسته خاصی است که در آن یک کلاس، متد، متغیر یا سازنده تعریف شده است.
  3. protected- این اصلاح کننده دسترسی همان سطح دسترسی را ارائه می دهد که package-privateبا اضافه کردن دسترسی برای کلاس هایی که یک کلاس را با protectedاصلاح کننده به ارث می برند.
  4. public- این سطح دسترسی برای کلاس ها نیز استفاده می شود. این سطح دسترسی به این معنی است که دسترسی کامل در سراسر برنامه وجود دارد.
50 پرسش و پاسخ برتر مصاحبه شغلی برای Java Core.  قسمت 1 - 2

10. متد overriding چیست؟

زمانی که یک کلاس فرزند می‌خواهد رفتار کلاس والد خود را تغییر دهد، روش‌ها را لغو می‌کنیم. اگر ما نیز نیاز به انجام آنچه در متد والد داریم، می‌توانیم از super.methodName() در فرزند استفاده کنیم که متد والد را اجرا می‌کند. بعد از آن می توانیم منطق اضافی خود را اضافه کنیم. الزاماتی که باید رعایت شود:
  • امضای روش باید یکسان باشد
  • مقدار بازگشتی باید یکسان باشد

11. امضای روش چیست؟

50 پرسش و پاسخ برتر مصاحبه شغلی برای Java Core.  قسمت 1 - 3امضای متد ترکیبی از نام متد و آرگومان هایی است که متد می گیرد. امضای متد، شناسه منحصر به فرد یک روش در هنگام بارگذاری بیش از حد متدها است.

12. اضافه بار روش چیست؟

اضافه بار روش یکی از ویژگی های چندشکلی است که در آن امضای متد را تغییر می دهیم تا چندین روش ایجاد کنیم که یک عمل را انجام می دهند:
  • همین نام
  • استدلال های مختلف
  • می تواند انواع مختلف بازگشت وجود داشته باشد
به عنوان مثال، متد ArrayListکلاس add()می تواند بیش از حد بارگذاری شود و به ما امکان می دهد بسته به آرگومان های ورودی به روش های مختلفی اضافه کنیم:
  • add(Object o)- این روش به سادگی یک شی را اضافه می کند
  • add(int index, Object o)- این روش یک شی را در یک شاخص خاص اضافه می کند
  • add(Collection<Object> c)- این روش لیستی از اشیا را اضافه می کند
  • add(int index, Collection<Object> c)- این روش فهرستی از اشیا را اضافه می کند که از یک شاخص خاص شروع می شوند.

13. رابط چیست؟

جاوا از وراثت چندگانه پشتیبانی نمی کند. برای غلبه بر این محدودیت، اینترفیس هایی به شکلی که ما می شناسیم و دوست داریم اضافه شدند. در چارچوب این پاسخ، اجازه دهید در مورد آنها صحبت کنیم. مثلا:

public interface Animal {
   void makeSound();
   void eat();
   void sleep();
}
برخی از جزئیات از این نتیجه می شود:
  • همه متدها در یک رابط عمومی و انتزاعی هستند
  • همه متغیرها نهایی استاتیک عمومی هستند
  • کلاس ها رابط ها را به ارث نمی برند (یعنی از کلمه کلیدی extensions استفاده نمی کنیم). در عوض، کلاس‌ها آن‌ها را پیاده‌سازی می‌کنند (یعنی از کلمه کلیدی implements استفاده می‌کنیم). علاوه بر این، شما می توانید هر تعداد رابط را که می خواهید پیاده سازی کنید.
  • کلاس هایی که یک اینترفیس را پیاده سازی می کنند باید پیاده سازی تمام متدهایی را که در اینترفیس هستند ارائه دهند.
مثل این:
public class Cat implements Animal {
   public void makeSound() {
       // Method implementation
   }

   public void eat() {
       // Implementation
   }

   public void sleep() {
       // Implementation
   }
}

14. روش پیش فرض در یک رابط چیست؟

حالا بیایید در مورد روش های پیش فرض صحبت کنیم. آنها برای چه کاری هستند؟ آنها برای چه کسانی هستند؟ این روش ها برای خدمت به "هر دو دست" اضافه شدند. من در مورد چه چیزی صحبت می کنم؟ خوب، از یک طرف، نیاز به اضافه کردن قابلیت های جدید وجود داشت: lambdas و Stream API. از سوی دیگر، لازم بود آنچه جاوا به آن معروف است حفظ شود - سازگاری با عقب. برای انجام این کار، اینترفیس ها به چند راه حل آماده جدید نیاز داشتند. روش های پیش فرض اینگونه به دست ما آمد. یک روش پیش‌فرض یک روش پیاده‌سازی شده در یک رابط است که با defaultکلمه کلیدی مشخص شده است. به عنوان مثال، روش شناخته شده stream()در Collectionرابط. باور کنید، این رابط به آن سادگی که به نظر می رسد نیست. یا همچنین forEach()روش به همان اندازه معروف در Iterableرابط. همچنین تا زمانی که روش های پیش فرض اضافه نشده بودند، وجود نداشت. به هر حال، شما همچنین می توانید در مورد آن در CodeGym اینجا بخوانید .

15. پس چگونه دو روش پیش فرض یکسان را به ارث می بریم؟

پاسخ قبلی در مورد اینکه یک روش پیش فرض چیست، سؤال دیگری را مطرح می کند. اگر بتوانید متدها را در اینترفیس ها پیاده سازی کنید، از نظر تئوری می توانید دو اینترفیس را با یک روش پیاده سازی کنید. چگونه ما آن را انجام دهیم؟ در اینجا دو رابط مختلف با یک روش وجود دارد:
interface A {
   default void foo() {
       System.out.println("Foo A");
   }
}

interface B {
   default void foo() {
       System.out.println("Foo B");
   }
}
و ما یک کلاس داریم که این دو رابط را پیاده سازی می کند. اما چگونه یک روش خاص را در رابط A یا B انتخاب کنیم؟ ساختار ویژه زیر این امکان را می دهد A.super.foo():
public class C implements A, B {
   public void fooA() {
       A.super.foo();
   }

   public void fooB() {
       B.super.foo();
   }
}
بنابراین، متد از روش پیش‌فرض اینترفیس fooA()استفاده می‌کند ، در حالی که متد از روش رابط استفاده می‌کند . foo()AfooB()foo()B

16. متدها و کلاس های انتزاعی چیست؟

در جاوا، abstractیک کلمه رزرو شده است. برای نشان دادن کلاس ها و متدهای انتزاعی استفاده می شود. ابتدا به تعاریف نیاز داریم. متد انتزاعی متدی است که با استفاده از abstractکلمه کلیدی بدون پیاده سازی در کلاس انتزاعی اعلان می شود. یعنی این یک روش مانند یک رابط است، اما با اضافه کردن یک کلمه کلیدی، به عنوان مثال:
public abstract void foo();
یک کلاس انتزاعی کلاسی است که با abstractکلمه کلیدی نیز مشخص شده است:
public abstract class A {

}
یک کلاس انتزاعی چندین ویژگی دارد:
  • شما نمی توانید یک شی از یک کلاس انتزاعی ایجاد کنید
  • می تواند روش های انتزاعی داشته باشد
  • همچنین ممکن است روش های انتزاعی نداشته باشد
کلاس‌های انتزاعی برای انتزاع (با عرض پوزش برای توتولوژی) که دارای مجموعه‌ای از رفتارها و حالت‌های مشترک است (یعنی روش‌ها و متغیرها) مورد نیاز است. زندگی واقعی پر از مثال است. همه چیز در اطراف ما «حیوان»، «ماشین»، «شکل هندسی» و غیره.

17. تفاوت بین String، StringBuilder و StringBuffer چیست؟

Stringمقادیر در یک مجموعه رشته ثابت ذخیره می شوند. به محض ایجاد رشته، در این استخر ظاهر می شود. و نمی توانید آن را حذف کنید. مثلا:
String name = "book";
متغیر به استخر رشته ثابت اشاره خواهد کرد. 50 پرسش و پاسخ برتر مصاحبه شغلی برای Java Core.  قسمت 1 - 4با تنظیم متغیر نام به مقدار متفاوت، داریم:
name = "pen";
مخزن رشته ثابت به این صورت است: 50 پرسش و پاسخ برتر مصاحبه شغلی برای Java Core.  قسمت 1 - 5به عبارت دیگر، هر دو مقدار در آنجا باقی می مانند. بافر رشته:
  • Stringمقادیر در یک پشته ذخیره می شوند. اگر مقداری تغییر کند، مقدار جدید جایگزین مقدار قبلی می شود.
  • String Bufferهماهنگ است و بنابراین ایمن است.
  • به دلیل ایمنی نخ، عملکرد آن ضعیف است.
مثال:
StringBuffer name = “book”;
50 پرسش و پاسخ برتر مصاحبه شغلی برای Java Core.  قسمت 1 - 6به محض اینکه مقدار متغیر نام تغییر کند، مقدار در پشته تغییر می کند: 50 پرسش و پاسخ برتر مصاحبه شغلی برای Java Core.  قسمت 1 - 7StringBuilder دقیقاً مشابه است StringBuffer، فقط thread safe نیست. در نتیجه، به طور قابل توجهی سریعتر از StringBuffer.

18. تفاوت بین یک کلاس انتزاعی و یک رابط چیست؟

کلاس چکیده:
  • کلاس های انتزاعی یک سازنده پیش فرض دارند. هر بار که یک نسل از کلاس انتزاعی ایجاد می شود، نامیده می شود.
  • آنها می توانند هم شامل روش های انتزاعی و هم روش های غیرانتزاعی باشند. به طور کلی، یک کلاس انتزاعی لزومی ندارد که متدهای انتزاعی داشته باشد.
  • کلاسی که یک کلاس انتزاعی را به ارث می برد باید فقط متدهای انتزاعی را پیاده سازی کند.
  • یک کلاس انتزاعی می تواند دارای متغیرهای نمونه باشد (به سوال شماره 5 مراجعه کنید).
رابط:
  • یک اینترفیس سازنده ندارد و نمی توان آن را مقدار دهی اولیه کرد.
  • فقط روش های انتزاعی را می توان اضافه کرد (به جز روش های پیش فرض).
  • کلاس هایی که اینترفیس را پیاده سازی می کنند باید همه متدها (به جز متدهای پیش فرض) را پیاده سازی کنند.
  • رابط ها فقط می توانند ثابت داشته باشند.

19. چرا دسترسی به یک عنصر در آرایه O(1) است؟

این سوال به معنای واقعی کلمه در آخرین مصاحبه من پرسیده شد. همانطور که بعداً فهمیدم، هدف از این سؤال این است که ببینیم یک شخص چگونه فکر می کند. واضح است که این دانش ارزش عملی کمی دارد. فقط دانستن آن کافی است. ابتدا باید توضیح دهیم که O(1) نشانه پیچیدگی زمانی یک الگوریتم "زمان ثابت" است. به عبارت دیگر، این نامگذاری سریعترین زمان اجرا را نشان می دهد. برای پاسخ به این سوال، باید آنچه را که در مورد آرایه ها می دانیم در نظر بگیریم. برای ایجاد یک intآرایه باید موارد زیر را بنویسیم:
int[] intArray = new int[100];
از این نحو می توان چندین نتیجه گرفت:
  1. وقتی یک آرایه اعلان می شود، نوع آن مشخص است. اگر نوع آن مشخص باشد، پس اندازه هر سلول در آرایه مشخص است.
  2. اندازه کل آرایه مشخص است.
بنابراین، برای اینکه بفهمیم در کدام سلول باید بنویسیم، فقط باید محاسبه کنیم که در کدام ناحیه از حافظه بنویسیم. برای کامپیوتر، این کار آسانی است. کامپیوتر می داند حافظه اختصاص داده شده از کجا شروع می شود، تعداد عناصر و اندازه هر سلول. همه اینها به این معنی است که محل نوشتن برابر با محل شروع آرایه + اندازه هر سلول ضرب در شاخص خواهد بود.

پس چگونه هنگام دسترسی به اشیاء در یک ArrayList به O(1) برسیم؟

این سوال بلافاصله بعد از سوال قبلی می آید. حقیقت این است که هنگام کار با آرایه‌ای که دارای مقادیر اولیه است، از قبل (در زمان ایجاد) اندازه نوع عنصر را می‌دانیم. اما اگر این نوع سلسله مراتب وراثت را داشته باشیم و 50 پرسش و پاسخ برتر مصاحبه شغلی برای Java Core.  قسمت 1 - 8بخواهیم یک مجموعه برای عناصر نوع A ایجاد کنیم و پیاده سازی های مختلف (B، C و D) را اضافه کنیم، چه کار می کنیم:
List<A> list = new ArrayList();
list.add(new B());
list.add(new C());
list.add(new D());
list.add(new B());
در این شرایط چگونه اندازه هر سلول را محاسبه کنیم؟ پس از همه، هر شی متفاوت خواهد بود، احتمالا با زمینه های اضافی متفاوت است. چه باید کرد؟ در اینجا سوال به گونه ای مطرح می شود که قصد دارد شما را گیج کند. ما می دانیم که مجموعه به طور مستقیم اشیاء را ذخیره نمی کند. فقط ارجاع به اشیا را ذخیره می کند. و همه مراجع یک اندازه دارند و معلوم است. در نتیجه، ما آدرس ها را در اینجا به همان روشی که در سوال قبل انجام دادیم محاسبه می کنیم.

21. اتوباکس و جعبه گشایی

پیشینه تاریخی: اتوباکسینگ و جعبه گشایی برخی از نوآوری های اصلی در JDK 5 هستند. اتوباکسینگ فرآیند تبدیل خودکار از یک نوع اولیه به یک کلاس بسته بندی مربوطه است. جعبه گشایی درست برعکس اتوباکسینگ است. این فرآیند تبدیل یک کلاس wrapper به یک اولیه است. اما اگر مقدار یک wrapper باشد null، a NullPointerExceptionدر حین جعبه گشایی پرتاب می شود.

اولیه ها و لفاف های مربوط به آنها

اولیه کلاس لفاف
بولی بولی
بین المللی عدد صحیح
بایت بایت
کاراکتر شخصیت
شناور شناور
طولانی طولانی
کوتاه کوتاه
دو برابر دو برابر

// اتوباکسینگ اتفاق می افتد:

  • هنگام اختصاص دادن یک بدوی به یک مرجع به یک کلاس wrapper:

    قبل از جاوا 5:

    // Manual boxing (the way it was BEFORE Java 5).
    public void boxingBeforeJava5() {
       Boolean booleanBox = new Boolean(true);
       Integer intBox = new Integer(3);
       // And so on for other types
    }
    
    After Java 5:
    // Automatic boxing (the way it became in Java 5).
    public void boxingJava5() {
       Boolean booleanBox = true;
       Integer intBox = 3;
       // And so on for other types
    }
  • هنگامی که یک اولیه به عنوان آرگومان به متدی ارسال می شود که انتظار یک wrapper را دارد:

    public void exampleOfAutoboxing() {
       long age = 3;
       setAge(age);
    }
    
    public void setAge(Long age) {
       this.age = age;
    }

// جعبه گشایی اتفاق می افتد:

  • وقتی نمونه ای از کلاس wrapper را به یک متغیر اولیه اختصاص می دهیم:

    // BEFORE Java 5:
    int intValue = new Integer(4).intValue();
    double doubleValue = new Double(2.3).doubleValue();
    char c = new Character((char) 3).charValue();
    boolean b = Boolean.TRUE.booleanValue();
    
    // And after JDK 5:
    int intValue = new Integer(4);
    double doubleValue = new Double(2.3);
    char c = new Character((char) 3);
    boolean b = Boolean.TRUE;
  • در حین انجام عملیات حسابی این عملیات فقط برای انواع اولیه اعمال می شود، بنابراین جعبه گشایی برای موارد اولیه ضروری است.

    // BEFORE Java 5:
    Integer integerBox1 = new Integer(1);
    Integer integerBox2 = new Integer(2);
    
    // A comparison used to require this:
    integerBox1.intValue() > integerBox2.intValue()
    
    // In Java 5
    integerBox1 > integerBox2
  • هنگام ارسال نمونه ای از کلاس wrapper به متدی که ابتدایی مربوطه را می گیرد:

    public void exampleOfAutoboxing() {
       Long age = new Long(3);
       setAge(age);
    }
    
    public void setAge(long age) {
       this.age = age;
    }

22. کلمه کلیدی نهایی چیست و کجا استفاده می شود؟

کلمه finalکلیدی را می توان بر روی متغیرها، متدها و کلاس ها استفاده کرد.
  1. مقدار متغیر نهایی پس از مقداردهی اولیه قابل تغییر نیست.
  2. کلاس آخر استریل است :) نمی تواند بچه دار شود.
  3. یک روش نهایی نمی تواند توسط یک نسل نادیده گرفته شود.
ما مسائل سطح بالا را پوشش داده ایم. حالا بیایید عمیق تر شیرجه بزنیم.

متغیرهای نهایی

جاوا دو راه به ما می دهد تا یک متغیر را اعلام کنیم و یک مقدار به آن اختصاص دهیم:
  1. می توانید یک متغیر را اعلام کنید و بعداً آن را مقداردهی اولیه کنید.
  2. شما می توانید یک متغیر را اعلام کنید و بلافاصله یک مقدار را تعیین کنید.
در اینجا یک مثال است که این استفاده از متغیرهای نهایی را نشان می دهد:
public class FinalExample {

   // A static final variable that is immediately initialized:
   final static String FINAL_EXAMPLE_NAME = "I'm likely the final one";

   // A final variable that is not initialized, but will only work if you
   // initialize it in the constructor:
   final long creationTime;

   public FinalExample() {
       this.creationTime = System.currentTimeMillis();
   }

   public static void main(String[] args) {
       FinalExample finalExample = new FinalExample();
       System.out.println(finalExample.creationTime);

       // The final FinalExample.FINAL_EXAMPLE_NAME field cannot be accessed
//    FinalExample.FINAL_EXAMPLE_NAME = "Not you're not!";

       // The final Config.creationTime field cannot be accessed
//    finalExample.creationTime = 1L;
   }
}

آیا می توان یک متغیر نهایی را ثابت در نظر گرفت؟

از آنجایی که نمی‌توانیم مقادیر جدیدی را به متغیرهای نهایی اختصاص دهیم، به نظر می‌رسد که اینها متغیرهای ثابت هستند. اما فقط در نگاه اول: اگر نوع داده متغیر باشد immutable، بله، ثابت است. اما اگر نوع داده mutable، یعنی قابل تغییر باشد، می توان از متدها و متغیرها برای تغییر مقدار شی مورد اشاره توسط متغیر استفاده کرد final. به همین دلیل نمی توان آن را ثابت نامید. مثال زیر نشان می دهد که برخی از متغیرهای نهایی واقعا ثابت هستند، در حالی که برخی دیگر ثابت نیستند، زیرا می توان آنها را تغییر داد.
public class FinalExample {

   // Immutable final variables
   final static String FINAL_EXAMPLE_NAME = "I'm likely the final one";
   final static Integer FINAL_EXAMPLE_COUNT  = 10;

   // Mutable final variables
   final List<String> addresses = new ArrayList();
   final StringBuilder finalStringBuilder = new StringBuilder("Constant?");
}

متغیرهای نهایی محلی

هنگامی که یک finalمتغیر در یک متد ایجاد می شود، به آن متغیر می گویند local final:
public class FinalExample {

   public static void main(String[] args) {
       // You can do this
       final int minAgeForDriveCar = 18;

       // Or you can do this, in a for-each loop:
       for (final String arg : args) {
           System.out.println(arg);
       }
   }

}
می‌توانیم از کلیدواژه نهایی در یک حلقه for تقویت‌شده استفاده کنیم، زیرا بعد از هر تکرار حلقه، متغیر جدیدی ایجاد می‌شود. به خاطر داشته باشید که این برای یک حلقه for معمولی صدق نمی کند، بنابراین یک خطای زمان کامپایل دریافت خواهیم کرد.
// The final local j variable cannot be assigned
for (final int i = 0; i < args.length; i ++) {
   System.out.println(args[i]);
}

کلاس پایانی

کلاس اعلام شده به عنوان finalقابل تمدید نیست. به بیان ساده تر، هیچ کلاس دیگری نمی تواند آن را به ارث ببرد. یک مثال عالی از یک finalکلاس در JDK String است. اولین قدم برای ایجاد یک کلاس تغییرناپذیر این است که آن را به عنوان علامت گذاری کنید final، بنابراین از گسترش آن جلوگیری کنید:
public final class FinalExample {
}

// Compilation error!
class WantsToInheritFinalClass extends FinalExample {
}

روش های نهایی

هنگامی که یک روش علامت نهایی می شود، به آن روش نهایی می گویند (معنی است، درست است؟). یک متد نهایی را نمی توان در کلاس فرزند لغو کرد. اتفاقاً متدهای wait() و notify() کلاس Object نهایی هستند، بنابراین ما توانایی لغو آنها را نداریم.
public class FinalExample {
   public final String generateAddress() {
       return "Some address";
   }
}

class ChildOfFinalExample extends FinalExample {

   // Compilation error!
   @Override
   public String generateAddress() {
       return "My OWN Address";
   }
}

نحوه و مکان استفاده از final در جاوا

  • از کلمه کلیدی نهایی برای تعریف برخی از ثابت های سطح کلاس استفاده کنید.
  • متغیرهای نهایی را برای اشیایی که نمی خواهید تغییر کنند ایجاد کنید. به عنوان مثال، ویژگی‌های شی خاص که می‌توانیم برای اهداف لاگ استفاده کنیم.
  • اگر نمی خواهید کلاسی تمدید شود، آن را به عنوان نهایی علامت بزنید.
  • اگر نیاز به ایجاد یک کلاس تغییرناپذیر دارید، باید آن را نهایی کنید.
  • اگر می‌خواهید پیاده‌سازی متد در نسل‌های آن تغییر نکند، متد را به‌عنوان علامت‌گذاری کنید final. این بسیار مهم است تا مطمئن شوید که اجرا تغییر نمی کند.

23. انواع متغیر و غیر قابل تغییر کدامند؟

قابل تغییر است

اشیاء قابل تغییر اشیایی هستند که حالت و متغیرهای آنها پس از ایجاد قابل تغییر است. نمونه هایی از کلاس های قابل تغییر عبارتند از StringBuilder و StringBuffer. مثال:
public class MutableExample {

   private String address;

   public MutableExample(String address) {
       this.address = address;
   }

   public String getAddress() {
       return address;
   }

   // This setter can change the name field
   public void setAddress(String address) {
       this.address = address;
   }

   public static void main(String[] args) {

       MutableExample obj = new MutableExample("First address");
       System.out.println(obj.getAddress());

       // We are updating the name field, so this is a mutable object
       obj.setAddress("Updated address");
       System.out.println(obj.getAddress());
   }
}

تغییرناپذیر

اشیاء تغییرناپذیر اشیائی هستند که حالت و متغیرهای آنها پس از ایجاد شیء قابل تغییر نیستند. یک کلید عالی برای HashMap، فکر نمی کنید؟ :) به عنوان مثال، رشته، عدد صحیح، دو و غیره. مثال:
// We'll make this class final so no one can change it
public final class ImmutableExample {

   private String address;

   ImmutableExample(String address) {
       this.address = address;
   }

   public String getAddress() {
       return address;
   }

   // We remove the setter

   public static void main(String[] args) {

       ImmutableExample obj = new ImmutableExample("Old address");
       System.out.println(obj.getAddress());

       // There is no way to change this field, so it is an immutable object
       // obj.setName("new address");
       // System.out.println(obj.getName());

   }
}
در قسمت بعدی به پرسش و پاسخ درباره مجموعه ها می پردازیم. نمایه من در GitHub 50 پرسش و پاسخ مصاحبه شغلی برتر برای Java Core. قسمت 2
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION