تعداد بازدید: 2387

Generics ها در جاوا

اگر بخواهید توابع و کلاس های شما حالت عمومی تر داشته باشد باید از متدها generic یا کلاس های generic استفاده کنید. به طور مثال متدی بنویسید که آرایه ای از هر جنس را بگیرد و تمامی المان های آن را چاپ کند. یا متدی داشته باشید که آرایه ای از هر جنس بگیرد و آن را مرتب کند کما این که این آرایه از جنس int باشد یا string .

generic ها این امکان را به ما می دهند که کلاس ها و اینترفیس ها و متدهایی تعریف کنیم که ورودی ها و خروجی هایی از نوع general داشته باشند.

نوع داده های مجاز برای استفاده در generic ها

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

Primitive Type Wrapper class
boolean Boolean
char Character
byte Byte
short Short
int Integer
long Long
float Float
double Double

زمانی که دارید یک کلاس یا متد generic را تعریف را فراخوانی می کنید ورودی خود را از نوع wrapper class تعریف کنید:

  • در زمان instance کلاس ها نوع داده wrapper class رو استفاده کنید.(معمولا نوع داده در زمان instance برای متد سازنده استفاده می شود)
  • یعنی نوع داده wrapper class رو بسازید و به متد مربوطه پاس بدید.

تعریف یک کلاس generic

public class CLASSNAME<PARAMSNAME>{}

مثلا

public class Gen<T>{}
  •   PARAMSNAMEیک نوع داده است که در طول کلاس یا متد می توان از آن استفاده کرد.
  • منظور از PARAMSNAME همان داده ایست که در زمان ساخت شی به آن داده می شود تا در سازنده از آن استفاده شود.
  • PARAMSNAME می تواندی یک یا چند پارامتر باشد که با , از هم جدا شده باشند.

instance گیری از کلاس های generic

CLASSNAME<WRAPPERCLASS_TYPES> VARIABLE = new CLASSNAME<>(PARAMS)

مثلا

Gen<Integer> g = new Gen<>(5);
  • در زمان نمونه گیری از کلاس generic باید نوع داده از جنس wrapper class را نیز در زمان نوع داده متغیر درجلو آن قرار داد.
  • PARAMS می تواند پارامتری از جنس نوع داده درونی wrapper class باشد.

مثال:

public class Box<T , E> {
    private T t;
    private E e;

    public Box(T t,E e){
        this.t = t;
        this.e = e;
    }

    public T get_t(){ return this.t; }

    public E get_e() { return this.e; }

    public static void main(String args[]){
        Box<Integer,Integer> b = new Box<>(10,20);
        int e = b.get_e();
        int t = b.get_t();

        System.out.printf("t is %d \ne is %d", t, e);
    }

}
  • در طول کلاس و متد های آن از T , E  به صورت یک نوع داده رفتار می کنیم.
  • در زمان instance گیری (عملا در زمان مقدار دهی به متد سازنده) از wrapper class ها استفاده می کنیم.
  • ما برای پارامتر های کلاس یا متد generic معمولا از نام های T , E استفاده می کنیم.

تعریف متد از نوع generic

در داخل یک کلاس ما می توانیم یک متد از نوع generic داشته باشیم که هم خروجی آن می تواند general باشد و هم ورودی آن می تواند general باشد و یا هر دو.

public <PARAMSNAME> OUTPUT_TYPE METHODNAME (PARAMSNAME){ }

مثلا

public static <T> void test(T t) { }

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

public class genMethod {
    public static <E> void printArray(E[] inputArray){
        for(E tmp: inputArray){
            System.out.println(tmp);
        }
    }
    public static <T> T test(T t){
        return t;
    }
    public static void main(String args[]){
        Integer int_arr[] = {1,2,3,4,5};
        String str_arr[] = {"mahdi","abolfazl","mohamad","kurosh"};
        Double dbl_arr[] = {1.2,2.8,6.4,5.3};

        System.out.println("* integer array *");
        genMethod.printArray(int_arr);

        System.out.println("* string array *");
        genMethod.printArray(str_arr);

        System.out.println("* double array *");
        genMethod.printArray(dbl_arr);
    }
}
  • متد test هم ورودی از نوع general دارد و خروجی.
  • متد printArray تنها ورودی از نوع general دارد.
  • در زمان فراخوانی متد printArray نوع داده ارجاعی را با استفاده از wrapper class ساختیم و بعد به متد generic دادیم.
  • شاخص <T> تعریف نوع پارامتر ورودی و خروجی در متد test هست.

محدودکردن پارامتر های generic

می تونیم با کلمه کلیدی extends پارامتر های generic رو محدود کنیم. مثلا متدی که فقط داده از نوع عددی (Number) بگیرد حال از نوع int , double , short , …

public class CLASSNAME<PARAMSNAME extends Number>{}

حال می تونه اون Number برابر با ورودی های رشته ای باشه .

public class restrictWCT<T extends Number> {
    private T t;

    public restrictWCT(T t){
        this.t = t;
    }

    public T get_t(){
        return this.t;
    }

    public static void main(String args[]){

        restrictWCT<Integer> r = new restrictWCT<>(10);
        int i = r.get_t();
        System.out.printf("integer is %d",i);
    }
}

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

اشتراک گذاری :

مدیر وب سایت گنوتک . برنامه نویسی رو با زبان C در هفده سالگی شروع کردم . در حال حاضر به برنامه نویسی php برپایه معماری MVC , HMVC و همچنین سیستم مدیریت محتوای WordPress و فریم ورک محبوب لاراول علاقه مند هستم و دوست دارم اطلاعاتم رو با شما به اشتراک بگذارم.

یک دیدگاه برای Generics ها در جاوا

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *