از کلمه کلیدی static برای مدیریت حافظه استفاده می شود؛ می توان گفت که کلمه کلیدی static بیشتر با خود کلاس ارتباط دارد تا با نمونه های ساخته شده از آن. از این کلمه کلیدی می توان در موارد زیر استفاده کرد:
در صورتی که موقع ساخت یک متغیر از کلمه کلیدی static استفاده شود آنگاه
مزیت استفاده از متغیر استاتیک این است که در مصرف حافظه صرفه جویی میشود.
class Student{ int rollno; String name; String college="ITS"; }
به قطعه کد بالا نگاه کنید. اگر قرار باشد که 500 نفر از دانشجویان این دانشگاه را وارد کنیم، 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 هنگام ساخت یه متد، آن متد:
مثال:
//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
محدودیت های متد استاتیک
دو محدودیت اصلی برای متدهای استاتیک وجود دارند که عبارتند از:
مثال:
class A{ int a=40;//non static public static void main(String args[]){ System.out.println(a); } }
خروجی:
Output:Compile Time Error
سوال: چرا متد main یک متد static است؟
تا نیاز برای ساخت یک شی برای استفاده از این متد نباشد زیرا در آن صورت مقداری حافظه اضافه توسط JVM مصرف میشد.
مثال:
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، اینکار توسط بلوک های استاتیک قابل انجام بود. توجه کنید:
مثال:
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 برای اشاره به متغیرهای کلاس مورد استفاده میشود. کد زیر را مشاهده کنید تا با این مشکل که گاها پیش میاید آشنا شوید:
مثال:
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
در مبحث 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 به عنوان پارامتر یک کانستراکتور استفاده می شود. به مثال توجه کنید:
مثال:
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
در صورتی که نوع داده بازگشتی یک متد از نوع همان کلاس باشد، از این کلمه کلیدی می توان برای بازگرداندن این نمونه استفاده کرد.
سینتکس:
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(); } }
خروجی:
A5@22b3ea59 A5@22b3ea59
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.