Static و This :
من ارسلان میربزرگی در این مقاله در مورد این دو کلمه کلیدی و کاربرد آنها در زبان جاوا با شما بیشتر صحبت خواهم کرد. در زبان جاوا کلمات کلیدی متعددی وجود دارند که نمیتوانید از آنها برای نامگذاری متغیرها و یا شناسهها استفاده کنید. static و this 2 کلمه کلیدی هستند که در این دسته بندی قرار میگیرند. کلمه کلیدی static در بحث مدیریت حافظه مورد استفاده قرار میگیرد و عمده ارتباط آن با خود کلاس است. کلمه کلیدی this نیز، دامنه کاربردی زیادی در زبان برنامه نویسی جاوا دارد. از این کلمه کلیدی برای اشاره به شی کنونی و شی بالایی استفاده میشود.

static و this در جاوا به چه صورت اند؟
گفتیم که کلمه کلیدی static در بحث مدیریت حافظه مورد استفاده قرار میگیرد و عمده ارتباط آن با خود کلاس است. از این کلمه کلیدی، در موارد زیر استفاده میشود :
• در مورد متغیر یا متغیر کلاس
• در مورد متد یا متد کلاس
• در مورد بلوک
• در مورد کلاس داخلی
متغیر استاتیک در جاوا
اگر در زبان جاوا، در زمان تولید یک متغیر، برنامه نویس از کلمه کلیدی static استفاده کند، باید از این متغیر برای ویژگیهای مشترک بین همه اعضای یک کلاس استفاده شود. به طور مثال نام شرکت برای کارکنان آن شرکت یا نام دانشگاه برای دانشجویان. علاوه بر این موضوع، متغیر استاتیک فقط یک مرتبه آن هم در موقعی که کلاس در حال لود شدن است، حافطه را دریافت میکند و از این نظر باید تمهیدات لازم توسط برنامه نویس، در نظر گرفته شود. مزیتی که استفاده از متغیر استاتیک در زبان جاوا دارد این است که در میزان حافظه مصرفی صرفه جویی میشود.
class Student{ int rollno; String name; String college="ITS"; }
کد بالا، مثالی برای استفاده از متغیر استاتیک در زبان جاوا است. فرض کنید لیستی شامل 500 دانشجو داریم. اگر قرار باشد برای تک تک آنها، نام دانشگاه را وارد کنیم، میزان حافظه مصرفی افزایش مییابد در صورتی که اگر از متغیر استاتیک استفاده کنیم، صرفا به میزان یک بار استفاده، حافظه در نظر گرفته میشود.
مثال :
//Program of static variable class Student8{ int rollno; String name; static String college ="ITS"; Student8(int r,String n){ rollno = r; name = n; } void display (){System.out.println(rollno+" "+name+" "+college);} public static void main(String args[]){ Student8 s1 = new Student8(111,"Karan"); Student8 s2 = new Student8(222,"Aryan"); s1.display(); s2.display(); } }
خروجی :
Output:111 Karan ITS 222 Aryan ITS
مقایسه بین شمارنده استاتیک و شمارنده غیر استاتیک
همانطور که مشاهده میکنید، در کد زیر متغیر counter به صورت استاتیک تعریف نشده است. بنابراین در این کد، هر شی دارای متغیر مخصوص به خود است که این متغیر در همه نمونه هایی که از این کلاس تولید میشود، متفاوت است. اگر به خروجی این کد دقت کنید، میبینید که این متغیر، در هر شی صرفا یک مرتبه اضافه شده است.
مثال :
class Counter{ int count=0;//will get memory when instance is created Counter(){ count++; System.out.println(count); } public static void main(String args[]){ Counter c1=new Counter(); Counter c2=new Counter(); Counter c3=new Counter(); } }
خروجی :
Output:1 1 1

در مثالی دیگر، این بار متغیر counter را به شکل استاتیک تعریف میکنیم. در نتیجه این متغیر، بین همه اعضای این کلاس مشترک خواهد بود. در این مثال اگر به مقادیر این متغیر چیزی اضافه شود، متغیر counter نیز به همان اندازه تغییر خواهد کرد. در این مثال به کد و خروجی آن توجه کنید.
مثال :
class Counter2{ static int count=0;//will get memory only once and retain its value Counter2(){ count++; System.out.println(count); } public static void main(String args[]){ Counter2 c1=new Counter2(); Counter2 c2=new Counter2(); Counter2 c3=new Counter2(); } }
خروجی :
Output:1 2 3
متد استاتیک در جاوا
اگر کلمه کلیدی static را در موقع تولید یک متد به کار ببرید، منجر به 3 اتفاق خواهد شد. اتفاق اول این است که این متد، دیگر یک نمونه ساخته شده از کلاس نیست و به کلاس تعلق دارد. اتفاق دوم این است که این متد بدون نیاز به ساخت هیچ نمونهای از کلاس، قابل فراخوانی است و سومین اتفاق نیز این است که این متد، قابلیت دسترسی به متغیرهای استاتیک و تغییر مقادیر آنها را دارد.
مثال :
//Program of changing the common property of all objects(static field). class Student9{ int rollno; String name; static String college = "ITS"; static void change(){ college = "BBDIT"; } Student9(int r, String n){ rollno = r; name = n; } void display (){System.out.println(rollno+" "+name+" "+college);} public static void main(String args[]){ Student9.change(); Student9 s1 = new Student9 (111,"Karan"); Student9 s2 = new Student9 (222,"Aryan"); Student9 s3 = new Student9 (333,"Sonoo"); s1.display(); s2.display(); s3.display(); } }
خروجی :
Output:111 Karan BBDIT 222 Aryan BBDIT 333 Sonoo BBDIT
به یک مثال دیگر نیز در این رابطه توجه کنید.
مثال :
//Program to get cube of a given number by static method class Calculate{ static int cube(int x){ return x*x*x; } public static void main(String args[]){ int result=Calculate.cube(5); System.out.println(result); } }
خروجی :
Output:125

متد استاتیک چه محدودیت هایی دارد؟
متدهای استاتیک دارای 2 محدودیت بزرگ میباشند. اولین محدودیت این است که این متدها، به متدهایی که استاتیک نیستند، دسترسی ندارند در نتیجه نمیتوانند آنها را فراخوانی کنند. دومین محدودیت این است که کلمات کلیدی this و super در این متدها قابل استفاده نیستند.
مثال :
class A{ int a=40;//non static public static void main(String args[]){ System.out.println(a); } }
خروجی :
Output:Compile Time Error
با توجه به این مثال، شاید برایتان این سوال ایجاد شده باشد که چرا متد main را به عنوان یک متد static در نظر میگیریم؟ در پاسخ این سوال باید بگوییم که علت این کار این است که در صورتی که بخواهیم از این متد استفاده کنیم، نیازی به ساخت یک شی دیگه و مصرف حافظه بیشتر نباشد.
بلوک استاتیک در جاوا
از بلوک استاتیک در زبان جاوا به منظور دادن یک مقدار اولیه به تک تک اعضای استاتیک استفاده میشود. بلوک استاتیک در زبان جاوا پیش از اجرا شدن متد main و در مرحله ای که کلاسها لود میشود، پیاده سازی میشود.
مثال :
class A2{ static{System.out.println("static block is invoked");} public static void main(String args[]){ System.out.println("Hello main"); } }
خروجی :
Output:static block is invoked Hello main
سوال دیگری که شاید پیش بیاید این است که آیا این امکان اجرای برنامهای بدون وجود متد main وجود دارد؟ در پاسخ این سوال نیز باید بگوییم که بله این امکان در JDK هایی که دارای ورژن پایین تر از ورژن 1.7، بودند، اجرای برنامه بدون نیاز به وجود متد main و به وسیله بلوک های استاتیک انجام میشد.
مثال :
class A3{ static{ System.out.println("static block is invoked"); System.exit(0); } }
خروجی :
Output:static block is invoked (if not JDK7)
خروجی این برنامه در نسخههای جدید :
Output:Error: Main method not found in class A3, please define the main method as: public static void main(String[] args)

کلمه کلیدی this در جاوا
کلیدی this، دامنه کاربردی زیادی در زبان جاوا دارد. از این کلمه کلیدی برای اشاره به شی کنونی و شی بالایی استفاده میشود. اگر بخواهیم کاربردهای این کلمه کلیدی را به صورت تیتروار بشماریم، میتوانیم به موارد زیر اشاره کنیم :
• اشاره به متغیر نمونه در کلاس خود
• فراخوانی متدهای یک کلاس به صورت ضمنی
• فراخوانی کانستراکتور یک کلاس
• استفاده به عنوان آرگومان در زمان فراخوانی متد
• استفاده به عنوان آرگومان در یک کانستراکتور
• برگرداندن نمونه تولید شده از یک کلاس، از داخل متد

اشاره به متغیر نمونه تولید شده در کلاس
اگر در زمان مقدار دهی در قسمتهایی مانند کانستراکتور و … ، نام متغیرهایی که در کلاس وجود دارند، با نام آرگومانهای ورودی یکسان باشند، کلمه کلیدی this مفید خواهد بود. از این کلمه کلید به منظور اشاره به متغیرهایی که در کلاس قرار دارند استفاده میشود. مثال زیر، نمونه ای از کاربرد این کلمه کلیدی است.
مثال :
class Student{ int rollno; String name; float fee; Student(int rollno,String name,float fee){ rollno=rollno; name=name; fee=fee; } void display(){System.out.println(rollno+" "+name+" "+fee);} } class TestThis1{ public static void main(String args[]){ Student s1=new Student(111,"ankit",5000f); Student s2=new Student(112,"sumit",6000f); s1.display(); s2.display(); }}
خروجی :
0 null 0.0 0 null 0.0
همانطور که مشاهده کردید، با اجرای این کد، مشکلی ایجاد شد و خروجی غیر صحیحی را تولید کرد. این مشکل توسط کد زیر اصلاح شده است.
مثال :
class Student{ int rollno; String name; float fee; Student(int rollno,String name,float fee){ this.rollno=rollno; this.name=name; this.fee=fee; } void display(){System.out.println(rollno+" "+name+" "+fee);} } class TestThis2{ public static void main(String args[]){ Student s1=new Student(111,"ankit",5000f); Student s2=new Student(112,"sumit",6000f); s1.display(); s2.display(); }}
خروجی :
111 ankit 5000 112 sumit 6000
البته برای جلوگیری از این مشکل، بهتر است برنامه را به صورتی بنویسید که این مشکلات ایجاد نشود. در مثال زیر، طریقه نوشتن این کد را به شما نشان دادهایم.
مثال :
class Student{ int rollno; String name; float fee; Student(int r,String n,float f){ rollno=r; name=n; fee=f; } void display(){System.out.println(rollno+" "+name+" "+fee);} } class TestThis3{ public static void main(String args[]){ Student s1=new Student(111,"ankit",5000f); Student s2=new Student(112,"sumit",6000f); s1.display(); s2.display(); }}
خروجی :
111 ankit 5000 112 sumit 6000
توصیه ما این است که برای متغیرها و آرگومان های خودتان، از کلمات و اسامی دارای معنی و مفهوم استفاده کنید و در صورتی که واقعا نیاز داشتید، از کلمه کلیدی this استفاده کنید.
فراخوانی متد در کلاس
از کلمه کلیدی this می توانید به منظور فراخوانی متدهای یک کلاس، استفاده کنید. در صورتی که از این کلمه کلیدی استفاده نکنید، کامپایلر به شکل خودکار، این کلمه کلیدی را به کد شما اضافه خواهد کرد.
مثال :
class A{ void m(){System.out.println("hello m");} void n(){ System.out.println("hello n"); //m();//same as this.m() this.m(); } } class TestThis4{ public static void main(String args[]){ A a=new A(); a.n(); }}
خروجی :
hello n hello m
فراخوانی کانستراکتور کلاس
فرض کنید کلاس شما چند کانستراکتور مختلف دارد و شما قصد دارید به منظور صرفه جویی در نوشتن کدها، از یکی از کانستراکتورهای خود در درون یک کانستراکتور دیگر بهره ببرید. در این حالت بهتر است از کلمه کلیدی this استفاده کنید.
مثال :
class A{ A(){System.out.println("hello a");} A(int x){ this(); System.out.println(x); } } class TestThis5{ public static void main(String args[]){ A a=new A(10); }}
خروجی :
hello a 10
در این مثال، همانطور که مشاهده میکنید، کانستراکتور فراخوانی شده، داری چند پارامتر است.
مثال :
class A{ A(){ this(5); System.out.println("hello a"); } A(int x){ System.out.println(x); } } class TestThis6{ public static void main(String args[]){ A a=new A(); }}
خروجی :
5 hello a
از this به منظور تشکیل یک زنجیره ارتباطی بین کانستراکتورها نیز استفاده میشود. علت این کار نیز بیشتر کوتاه تر کردن کد و زیباتر شدن آن است.
مثال:
class Student{ int rollno; String name,course; float fee; Student(int rollno,String name,String course){ this.rollno=rollno; this.name=name; this.course=course; } Student(int rollno,String name,String course,float fee){ this(rollno,name,course);//reusing constructor this.fee=fee; } void display(){System.out.println(rollno+" "+name+" "+course+" "+fee);} } class TestThis7{ public static void main(String args[]){ Student s1=new Student(111,"ankit","java"); Student s2=new Student(112,"sumit","java",6000f); s1.display(); s2.display(); }}
خروجی:
111 ankit java null 112 sumit java 6000
باید توجه داشته باشید که کلمه کلیدی this لازم است تا حتما در اولین خط از کانستراکتور نوشته شود.
مثال:
class Student{ int rollno; String name,course; float fee; Student(int rollno,String name,String course){ this.rollno=rollno; this.name=name; this.course=course; } Student(int rollno,String name,String course,float fee){ this.fee=fee; this(rollno,name,course);//C.T.Error } void display(){System.out.println(rollno+" "+name+" "+course+" "+fee);} } class TestThis8{ public static void main(String args[]){ Student s1=new Student(111,"ankit","java"); Student s2=new Student(112,"sumit","java",6000f); s1.display(); s2.display(); }}
خروجی:
Compile Time Error: Call to this must be first statement in constructor
استفاده از کلمه کلیدی this به عنوان آرگومان ورودی در یک متد
در بحث Event Handling ممکن است از کلمه کلیدی this به عنوان آرگومان ورودی در یک متد استفاده شود.
مثال :
class S2{ void m(S2 obj){ System.out.println("method is invoked"); } void p(){ m(this); } public static void main(String args[]){ S2 s1 = new S2(); s1.p(); } }
خروجی :
method is invoked
در واقع در بحث Event Handling در زمانی که لازم است تا برای یک کلاس، رفرنس در نظر گرفته شود، از این کلمه کلیدی استفاده میشود.
استفاده از کلمه کلیدی this در هنگام فراخوانی کانستراکتور
با استفاده از این ویژگی، می توانید از کلمه کلیدی this به عنوان یک پارامتر برای کانستراکتور استفاده کنید.
مثال :
class B{ A4 obj; B(A4 obj){ this.obj=obj; } void display(){ System.out.println(obj.data);//using data member of A4 class } } class A4{ int data=10; A4(){ B b=new B(this); b.display(); } public static void main(String args[]){ A4 a=new A4(); } }
خروجی :
Output:10
استفاده از کلمه کلیدی this به منظور برگرداندن نمونه تولید شده
اگر نوع داده بازگشتی در یک متد، از نوع همان کلاس باشد، می توانیم با استفاده از کلمه کلیدی this برای برگرداندن این نمونه استفاده کنیم.
سینتکس :
return_type method_name(){ return this; }
مثال :
class A{ A getA(){ return this; } void msg(){System.out.println("Hello java");} } class Test1{ public static void main(String args[]){ new A().getA().msg(); } }
خروجی :
Hello java
در پایان این مقاله، کلمه کلیدی this را تست میکنیم که ببینیم آیا این کلمه کلیدی، قادر به برگرداندن همان نمونه کلاس است یا نه؟ در مثال زیر این تست را انجام دادهایم.
مثال :
class A5{ void m(){ System.out.println(this);//prints same reference ID } public static void main(String args[]){ A5 obj=new A5(); System.out.println(obj);//prints the reference ID obj.m(); } }
خروجی :
[email protected] [email protected]
و در آخر
وبسایت میربزرگی قصد دارد تا با ارائه مقاله ها و تجربههای کاربردی شما را در زمینه یادگیری و رفع اشکالاتتان کمک کند. در صورت وجود هرگونه سوالی به من ایمیل بزنید.
خیلی عالی و کاربردی
من میتونم چندتا سوال تو ایمیل بپرسم ازتون؟
بله حتما
مثال ها کامل و کاربردی ممنون از انتشار مقاله
سپاس