آموزش جاوا - Generics
عالی بود که میتوانستیم یک متد مرتبسازی واحد بنویسیم که بتواند عناصر در یک آرایهٔ Integer، یک آرایهٔ String یا یک آرایهٔ هر نوع دیگری که قابل مرتبسازی است را مرتب کند.
متدها و کلاسهای جنریک جاوا به برنامهنویسان اجازه میدهند تا با یک تعریف متد واحد، مجموعهای از متدهای مرتبط یا با یک تعریف کلاس واحد، مجموعهای از انواع مرتبط را مشخص کنند.
جنریکها همچنین امنیت نوع زمان کامپایل را فراهم میکنند که به برنامهنویسان اجازه میدهد نوعهای نامعتبر را در زمان کامپایل شناسایی کنند.
با استفاده از مفهوم جنریک جاوا، ممکن است یک متد جنریک برای مرتبسازی یک آرایهٔ اشیاء بنویسیم و سپس این متد جنریک را با آرایههای Integer، آرایههای Double، آرایههای String و غیره فراخوانی کنیم تا عناصر آرایه را مرتب کنیم.
متدهای جنریک
میتوانید یک تعریف متد جنریک واحد بنویسید که با آرگومانهای انواع مختلف فراخوانی شود. براساس نوع آرگومانهای ارسال شده به متد جنریک، کامپایلر هر فراخوانی متد را به درستی پردازش میکند. قوانین تعریف متدهای جنریک به شرح زیر است:
-
همهٔ تعریفهای متدهای جنریک دارای بخشی به نام بخش پارامتر نوع است که بین علامتهای سر برگها (< و >) قرار دارد و قبل از نوع بازگشتی متد قرار میگیرد (در مثال بعدی، < E > است).
-
هر بخش پارامتر نوع شامل یک یا چند پارامتر نوع است که با کاماها جدا میشوند. پارامتر نوع، همچنین به عنوان یک متغیر نوع شناخته میشود و یک شناسه است که نام نوع جنریک را مشخص میکند.
-
پارامترهای نوع میتوانند برای تعریف نوع بازگشتی و به عنوان جایگزینهایی برای نوعهای آرگومانهای ارسال شده به متد جنریک استفاده شوند.
-
بدنهٔ متد جنریک به همان روشی که برای هر متد دیگری تعریف میشود، تعریف میشود. توجه کنید که پارامترهای نوع تنها میتوانند نوعهای مرجع را نشان دهند و نوعهای ابتدایی (مانند int، double و char) نیستند.
مثال
مثال زیر نشان میدهد چگونه میتوانیم با استفاده از یک متد جنریک واحد، یک آرایهٔ انواع مختلف را چاپ کنیم −
public class GenericMethodTest {
// generic method printArray
public static < E > void printArray( E[] inputArray ) {
// Display array elements
for(E element : inputArray) {
System.out.printf("%s ", element);
}
System.out.println();
}
public static void main(String args[]) {
// Create arrays of Integer, Double and Character
Integer[] intArray = { 1, 2, 3, 4, 5 };
Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4 };
Character[] charArray = { 'H', 'E', 'L', 'L', 'O' };
System.out.println("Array integerArray contains:");
printArray(intArray); // pass an Integer array
System.out.println("\nArray doubleArray contains:");
printArray(doubleArray); // pass a Double array
System.out.println("\nArray characterArray contains:");
printArray(charArray); // pass a Character array
}
}
این عمل موجب تولید نتیجهٔ زیر میشود −
خروجی
Array integerArray contains:
1 2 3 4 5
Array doubleArray contains:
1.1 2.2 3.3 4.4
Array characterArray contains:
H E L L O
پارامترهای نوع محدودشده (Bounded Type Parameters)
گاهی اوقات ممکن است بخواهید نوعهایی که مجاز به ارسال شدن هستند را محدود کنید.
public class MaximumTest {
// determines the largest of three Comparable objects
public static <T extends Comparable<T>> T maximum(T x, T y, T z) {
T max = x; // assume x is initially the largest
if(y.compareTo(max) > 0) {
max = y; // y is the largest so far
}
if(z.compareTo(max) > 0) {
max = z; // z is the largest now
}
return max; // returns the largest object
}
public static void main(String args[]) {
System.out.printf("Max of %d, %d and %d is %d\n\n",
3, 4, 5, maximum( 3, 4, 5 ));
System.out.printf("Max of %.1f,%.1f and %.1f is %.1f\n\n",
6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ));
System.out.printf("Max of %s, %s and %s is %s\n","pear",
"apple", "orange", maximum("pear", "apple", "orange"));
}
}
این کد نتیجهٔ زیر را تولید خواهد کرد −
خروجی
Max of 3, 4 and 5 is 5
Max of 6.6,8.8 and 7.7 is 8.8
Max of pear, apple and orange is pear
کلاسهای جنریک (Generic Classes)
تعریف یک کلاس جنریک شبیه به تعریف یک کلاس غیرجنریک است، به استثنای این که نام کلاس پس از بخش پارامتر نوع آورده میشود.
مانند متدهای جنریک، بخش پارامتر نوع یک کلاس جنریک میتواند شامل یک یا چند پارامتر نوع باشد که با کاماها جدا میشوند. این کلاسها به عنوان کلاسهای پارامتریشده یا انواع پارامتریشده شناخته میشوند زیرا یک یا چند پارامتر را قبول میکنند.
مثال
مثال زیر نشان میدهد چگونه میتوانیم یک کلاس جنریک تعریف کنیم −
public class Box<T> {
private T t;
public void add(T t) {
this.t = t;
}
public T get() {
return t;
}
public static void main(String[] args) {
Box<Integer> integerBox = new Box<Integer>();
Box<String> stringBox = new Box<String>();
integerBox.add(new Integer(10));
stringBox.add(new String("Hello World"));
System.out.printf("Integer Value :%d\n\n", integerBox.get());
System.out.printf("String Value :%s\n", stringBox.get());
}
}
این به نتیجهٔ زیر منجر میشود −
خروجی
Integer Value :10
String Value :Hello World