فصل 18: بلوک آغازگر نمونه و کلمه کلیدی final در جاوا

28 مرداد 1397
java-final-keywords

از بلوک آغازگر نمونه (Instance Initializer block) برای مقداردهی اولیه به فیلدهای اشیا استفاده می شود. همانطور که قبلا هم دیدیم، این کار را می توان به صورت مستقیم نیز انجام داد اما اگر نیاز باشد تا علاوه بر مقداردهی، عملیات‌های اضافه تری نیز انجام شود، آنگاه از این بلوک استفاده می شود. هر زمان که یک نمونه از کلاس ساخته شود، این بلوک اجرا خواهد شد.

در ادامه دلیل استفاده از این بلوک را بررسی می کنیم.

چرا از بلوک آغازگر استفاده کنیم؟

در صورتی که بخواهیم علاوه بر تخصیص مقدار، عملیات های بیشتری همانند پر کردن یک آرایه پیچیده یا هندل ارورها انجام دهیم، از این بلوک استفاده می شود.

در مثال زیر تنها آغاز فیلدهای نمونه در این بلوک انجام می شود:

مثال:

class Bike7{  
    int speed;  
      
    Bike7(){System.out.println("speed is "+speed);}  
   
    {speed=100;}  
       
    public static void main(String args[]){  
    Bike7 b1=new Bike7();  
    Bike7 b2=new Bike7();  
    }      
}

خروجی:

Output:speed is 100
       speed is 100

در جاوا به طور کلی تنها در مکان های زیر امکان انجام عملیات‌ها وجود دارد:

  1. متد
  2. کانستراکتور
  3. بلوک

اول کدام صدا زده می شود: کانستراکتور یا بلوک آغازگر نمونه؟

مثال:

class Bike8{  
    int speed;  
      
    Bike8(){System.out.println("constructor is invoked");}  
   
    {System.out.println("instance initializer block invoked");}  
       
    public static void main(String args[]){  
    Bike8 b1=new Bike8();  
    Bike8 b2=new Bike8();  
    }      
}

خروجی:

Output:instance initializer block invoked
       constructor is invoked
       instance initializer block invoked
       constructor is invoked

با توجه به خروجی مثال بالا، این گمان می رود که ابتدا بلوک صدا زده می شود اما نادرست است. در واقع اتفاقی که می افتد این است که بلوک هنگام ساخت شی صدا زده می شود و کامپایلر آنرا در کانستراکتور کپی می کند تا بعد از super() اجرا شود. پس ابتدا کانستراکتور صدا زده می شود. در شکل زیر این مفهوم به نمایش در آمده است.

بلوک آغازگر در جاوا

قوانین برای بلوک آغازگر

به طور کلی 3 قانون وجود دارد:

  1. بلوک آغازگر هنگام ساخت یک شی، ساخته می شود.
  2. بلوک آغازگر درست پس از صدا زدن کانستراکتور کلاس پدر با super() صدا زده می شود.
  3. این بلوک به همان ترتیبی که دارد، اجرا می شود.

در مثال زیر اجرای بلوک پس از super() به نمایش در آمده است:

مثال:

class A{  
A(){  
System.out.println("parent class constructor invoked");  
}  
}  
class B2 extends A{  
B2(){  
super();  
System.out.println("child class constructor invoked");  
}  
  
{System.out.println("instance initializer block is invoked");}  
  
public static void main(String args[]){  
B2 b=new B2();  
}  
}

خروجی:

Output:parent class constructor invoked
       instance initializer block is invoked
       child class constructor invoked

حال مثالی دیگر را با هم ببینیم:

مثال:

class A{  
A(){  
System.out.println("parent class constructor invoked");  
}  
}  
  
class B3 extends A{  
B3(){  
super();  
System.out.println("child class constructor invoked");  
}  
  
B3(int a){  
super();  
System.out.println("child class constructor invoked "+a);  
}  
  
{System.out.println("instance initializer block is invoked");}  
  
public static void main(String args[]){  
B3 b1=new B3();  
B3 b2=new B3(10);  
}  
}

خروجی:

Output:parent class constructor invoked
       instance initializer block is invoked
       child class constructor invoked
       parent class constructor invoked
       instance initializer block is invoked
       child class constructor invoked 10

کلمه کلیدی final

از کلمه کلیدی final برای محدود کردن کاربر استفاده می شود. این کلمه کلیدی را می توان برای متد، کلاس و متغیر استفاده کرد.

در صورتی که متغیر خود را final تعریف کنیم و آنرا مقداردهی نکنیم، به آن متغیر خالی (blank final variable) میگویند و تنها از طریق کانستراکتور قابل مقداردهی است. همچنین این متغیر را میتوان استاتیک نیز تعریف کرد که در آن صورت تنها در بلوک استاتیک قابل مقداردهی است. ابتدا بگذارید موارد پایه ای تر را در مورد کلمه کلیدی final یاد بگیریم.

1- متغیر final در جاوا

در صورتی که یک متغیر را final تعریف کنید، آنگاه دیگر مقدار آن قابل تغییر نیست و یک ثابت (constant) به حساب می آید.

مثال:

class Bike9{  
 final int speedlimit=90;//final variable  
 void run(){  
  speedlimit=400;  
 }  
 public static void main(String args[]){  
 Bike9 obj=new  Bike9();  
 obj.run();  
 }  
}//end of class

خروجی:

Output:Compile Time Error

در مثال بالا متغیر speedlimit به شکل final تعریف شده است. به همین دلیل تغییر مقدار آن خطایی را به هنگام کامپایل نمایش می دهد.

2- متد final در جاوا

متدی که به صورت final تعریف شده باشد را نمی توان در ادامه override کرد.

مثال:

class Bike{  
  final void run(){System.out.println("running");}  
}  
     
class Honda extends Bike{  
   void run(){System.out.println("running safely with 100kmph");}  
     
   public static void main(String args[]){  
   Honda honda= new Honda();  
   honda.run();  
   }  
}

خروجی:

Output:Compile Time Error

3- کلاس final در جاوا

همانطور که باید پیش بینی کنید، در صورتی که یک کلاس را final تعریف کنید آنگاه نمیتوان از آن ارث بری کرد.

مثال:

final class Bike{}  
  
class Honda1 extends Bike{  
  void run(){System.out.println("running safely with 100kmph");}  
    
  public static void main(String args[]){  
  Honda1 honda= new Honda1();  
  honda.run();  
  }  
}

خروجی:

next →← prev
Final Keyword In Java
Final variable
Final method
Final class
Is final method inherited ?
Blank final variable
Static blank final variable
Final parameter
Can you declare a final constructor
The final keyword in java is used to restrict the user. The java final keyword can be used in many context. Final can be:

variable
method
class
The final keyword can be applied with the variables, a final variable that have no value it is called blank final variable or uninitialized final variable. It can be initialized in the constructor only. The blank final variable can be static also which will be initialized in the static block only. We will have detailed learning of these. Let's first learn the basics of final keyword.

final keyword in java
1) Java final variable
If you make any variable as final, you cannot change the value of final variable(It will be constant).

Example of final variable
There is a final variable speedlimit, we are going to change the value of this variable, but It can't be changed because final variable once assigned a value can never be changed.

class Bike9{  
 final int speedlimit=90;//final variable  
 void run(){  
  speedlimit=400;  
 }  
 public static void main(String args[]){  
 Bike9 obj=new  Bike9();  
 obj.run();  
 }  
}//end of class  
Test it Now
Output:Compile Time Error

 
2) Java final method
If you make any method as final, you cannot override it.

Example of final method
class Bike{  
  final void run(){System.out.println("running");}  
}  
     
class Honda extends Bike{  
   void run(){System.out.println("running safely with 100kmph");}  
     
   public static void main(String args[]){  
   Honda honda= new Honda();  
   honda.run();  
   }  
}  
Test it Now
Output:Compile Time Error
3) Java final class
If you make any class as final, you cannot extend it.

Example of final class
final class Bike{}  
  
class Honda1 extends Bike{  
  void run(){System.out.println("running safely with 100kmph");}  
    
  public static void main(String args[]){  
  Honda1 honda= new Honda1();  
  honda.run();  
  }  
}  
Test it Now
Output:Compile Time Error

سوال: آیا متدهای final به ارث می رسند؟

بله. فقط نمی شود آنها را اورراید کرد و گرنه به کلاس فرزند منتقل می شوند. به مثال زیر دقت کنید.

مثال:

class Bike{  
  final void run(){System.out.println("running...");}  
}  
class Honda2 extends Bike{  
   public static void main(String args[]){  
    new Honda2().run();  
   }  
}

خروجی:

Output:running...

سوال: منظور متغیر خالی (final blank final variable) چیست؟

در صورتی که همانند قطعه کد زیر، متغیری را final تعریف کنید اما آنرا مقداردهی نکنید. یک متغیر خالی final داریم که تنها از طریق کانستراکتور می توان آنرا مقداردهی کرد.

مثال:

class Student{  
int id;  
String name;  
final String PAN_CARD_NUMBER;  
...  
}  

در مثال زیر، مقداردهی به متغیر  final را در کانستراکتور می بینیم:

مثال:

class Bike10{  
  final int speedlimit;//blank final variable  
    
  Bike10(){  
  speedlimit=70;  
  System.out.println(speedlimit);  
  }  
  
  public static void main(String args[]){  
    new Bike10();  
 }  
}

خروجی:

Output: 70

متغیرهای static blank final

همانطور که در قطعه کد زیر می بینید، اگر یک متغیر final مقداردهی نشده را static تعریف کنیم؛ آنگاه یک متغیر static blank final داریم که تنها در بلوک استاتیک قابل مقداردهی است.

مثال:

class A{  
  static final int data;//static blank final variable  
  static{ data=50;}  
  public static void main(String args[]){  
    System.out.println(A.data);  
 }  
}

سوال: پارامتر final چیست؟

در صورتی که پارامتر ورودی متد را final تعریف کنیم آنگاه امکان تغییر آن وجود ندارد.

مثال:

class Bike11{  
  int cube(final int n){  
   n=n+2;//can't be changed as n is final  
   n*n*n;  
  }  
  public static void main(String args[]){  
    Bike11 b=new Bike11();  
    b.cube(5);  
 }  
}

خروجی:

Output: Compile Time Error

سوال: آیا امکان تعریف پارامتر به شکل final وجود دارد؟

خیر زیرا کانستراکتور هیچوقت به ارث نمی رسد.

نویسنده شوید
دیدگاه‌های شما

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.