JavaRush /جاوا بلاگ /Random-UR /جنرک کے ساتھ کام کرتے وقت varargs کا استعمال کرنا

جنرک کے ساتھ کام کرتے وقت varargs کا استعمال کرنا

گروپ میں شائع ہوا۔
ہیلو! آج کے سبق میں ہم generics کا مطالعہ جاری رکھیں گے۔ ایسا ہی ہوتا ہے کہ یہ ایک بڑا موضوع ہے، لیکن اس میں جانے کے لیے کہیں نہیں ہے - یہ زبان کا ایک انتہائی اہم حصہ ہے :) جب آپ اوریکل دستاویزات کا جنرکس پر مطالعہ کریں گے یا انٹرنیٹ پر گائیڈز پڑھیں گے، تو آپ کو شرائط معلوم ہوں گی۔ غیر قابل تجدید اقسام اور قابل تجدید اقسام ۔ "Reifiable" کس قسم کا لفظ ہے؟ یہاں تک کہ اگر انگریزی کے ساتھ سب کچھ اچھا ہے، تو آپ کو اس سے ملنے کا امکان نہیں ہے۔ آئیے ترجمہ کرنے کی کوشش کریں! جنرک کے ساتھ کام کرتے وقت ورارگز کا استعمال - 2
*شکریہ گوگل، آپ نے بہت مدد کی -_-*
قابل تجدید قسم ایک قسم ہے جس کی معلومات رن ٹائم پر پوری طرح دستیاب ہوتی ہے۔ جاوا زبان میں، ان میں قدیم، خام قسمیں، اور غیر عام قسمیں شامل ہیں۔ اس کے برعکس، غیر قابل تجدید قسمیں ایسی قسمیں ہیں جن کی معلومات کو مٹا دیا جاتا ہے اور رن ٹائم پر دستیاب نہیں کیا جاتا ہے۔ یہ صرف عام ہیں - List<String> ، List<Integer> ، وغیرہ۔

ویسے، کیا آپ کو یاد ہے کہ varargs کیا ہیں ؟

اگر آپ بھول گئے ہیں تو، یہ متغیر لمبائی کے دلائل ہیں۔ وہ ایسے حالات میں کارآمد ہوتے ہیں جہاں ہم بالکل نہیں جانتے کہ ہمارے طریقہ کار پر کتنے دلائل پاس کیے جا سکتے ہیں۔ مثال کے طور پر، اگر ہمارے پاس کیلکولیٹر کلاس ہے اور اس کا ایک طریقہ ہے sum۔ آپ طریقہ میں sum()2 نمبر، 3، 5، یا جتنے بھی آپ چاہیں پاس کر سکتے ہیں ۔ sum()تمام ممکنہ اختیارات کو مدنظر رکھتے ہوئے ہر بار طریقہ کو اوورلوڈ کرنا بہت عجیب ہوگا ۔ اس کے بجائے ہم یہ کر سکتے ہیں:
public class SimpleCalculator {

   public static int sum(int...numbers) {

       int result = 0;

       for(int i : numbers) {

           result += i;
       }

       return result;
   }

   public static void main(String[] args) {

       System.out.println(sum(1,2,3,4,5));
       System.out.println(sum(2,9));
   }
}
کنسول آؤٹ پٹ:

15
11
varargsلہذا، جنرک کے ساتھ استعمال میں کچھ اہم خصوصیات ہیں۔ آئیے اس کوڈ کو دیکھیں:
import javafx.util.Pair;
import java.util.ArrayList;
import java.util.List;

public class Main {

   public static <E> void addAll(List<E> list, E... array) {

       for (E element : array) {
           list.add(element);
       }
   }

   public static void main(String[] args) {
       addAll(new ArrayList<String>(),  //  здесь все нормально
               "Leonardo da Vinci",
               "Vasco de Gama"
       );

       // а здесь мы получаем предупреждение
       addAll(new ArrayList<Pair<String, String>>(),
               new Pair<String, String>("Leonardo", "da Vinci"),
               new Pair<String, String>("Vasco", "de Gama")
       );
   }
}
یہ طریقہ ایک فہرست اور کسی بھی تعداد میں اشیاء کو addAll()بطور input لیتا ہے ، اور پھر ان تمام اشیاء کو فہرست میں شامل کرتا ہے۔ طریقہ کار میں ہم اپنے طریقہ کو دو بار کہتے ہیں ۔ پہلی بار ہم دو باقاعدہ لائنوں میں شامل کرتے ہیں۔ یہاں سب کچھ ٹھیک ہے۔ دوسری بار ہم دو اشیاء میں اضافہ کرتے ہیں ۔ اور یہاں ہمیں اچانک ایک انتباہ ملتا ہے: List<E>Emain()addAll()ListListPair<String, String>

Unchecked generics array creation for varargs parameter
اس کا کیا مطلب ہے؟ ہمیں انتباہ کیوں ملتا ہے اور اس کا اس سے کیا تعلق ہے array؟ Array- یہ ایک صف ہے، اور ہمارے کوڈ میں کوئی صفیں نہیں ہیں! آئیے دوسرے سے شروع کرتے ہیں۔ انتباہ ایک صف کا ذکر کرتا ہے کیونکہ مرتب کرنے والا متغیر لمبائی کے دلائل (varargs) کو ایک صف میں تبدیل کرتا ہے۔ دوسرے الفاظ میں، ہمارے طریقہ کار کے دستخط ہیں addAll():
public static <E> void addAll(List<E> list, E... array)
یہ اصل میں اس طرح لگتا ہے:
public static <E> void addAll(List<E> list, E[] array)
یعنی، طریقہ میں main()، مرتب کرنے والا ہمارے کوڈ کو اس میں تبدیل کر دے گا:
public static void main(String[] args) {
   addAll(new ArrayList<String>(),
      new String[] {
        "Leonardo da Vinci",
        "Vasco de Gama"
      }
   );
   addAll(new ArrayList<Pair<String,String>>(),
        new Pair<String,String>[] {
            new Pair<String,String>("Leonardo","da Vinci"),
            new Pair<String,String>("Vasco","de Gama")
        }
   );
}
صف کے ساتھ سب کچھ ٹھیک ہے String۔ لیکن ایک صف کے ساتھ Pair<String, String>- نہیں۔ حقیقت یہ ہے کہ Pair<String, String>یہ ایک Non-Reifiable Type ہے۔ تالیف کے دوران، پیرامیٹر کی اقسام (<String, String>) کے بارے میں تمام معلومات کو مٹا دیا جائے گا۔ جاوا میں Non-Reifiable Type سے arrays بنانے کی اجازت نہیں ہے ۔ آپ اس کی تصدیق کر سکتے ہیں اگر آپ دستی طور پر ایک صف بنانے کی کوشش کرتے ہیں جوڑا<String, String>
public static void main(String[] args) {

   //  ошибка компиляции! Generic array creation
  Pair<String, String>[] array = new Pair<String, String>[10];
}
وجہ واضح ہے - قسم کی حفاظت۔ جیسا کہ آپ کو یاد ہے، ایک صف بناتے وقت، آپ کو یہ بتانا ضروری ہے کہ یہ سرنی کون سی اشیاء (یا قدیم چیزیں) ذخیرہ کرے گی۔
int array[] = new int[10];
پچھلے اسباق میں سے ایک میں، ہم نے قسم کو مٹانے کے طریقہ کار کا تفصیل سے جائزہ لیا۔ لہذا، اس صورت میں، قسموں کو مٹانے کے نتیجے میں، ہم نے وہ معلومات کھو دی ہیں کہ Pairجوڑے ہماری اشیاء میں محفوظ تھے <String, String>۔ ایک صف بنانا غیر محفوظ ہو گا۔ کے ساتھ اور جنرکس کے طریقے استعمال کرتے وقت varargs، ٹائپ ایریزر کے بارے میں یاد رکھنا یقینی بنائیں اور یہ کہ یہ کیسے کام کرتا ہے۔ اگر آپ کو اپنے لکھے ہوئے کوڈ پر مکمل اعتماد ہے، اور آپ جانتے ہیں کہ اس سے کوئی پریشانی نہیں ہوگی، تو آپ varargsتشریح کا استعمال کرتے ہوئے اس سے منسلک وارننگ کو غیر فعال کر سکتے ہیں۔@SafeVarargs
@SafeVarargs
public static <E> void addAll(List<E> list, E... array) {

   for (E element : array) {
       list.add(element);
   }
}
اگر آپ اس تشریح کو اپنے طریقہ کار میں شامل کرتے ہیں، تو ہمیں پہلے ملنے والی وارننگ ظاہر نہیں ہوگی۔ جنرک کو ایک ساتھ استعمال کرتے وقت ایک اور ممکنہ مسئلہ varargsڈھیر کی آلودگی ہے۔ جنرک کے ساتھ کام کرتے وقت ورارگز کا استعمال - 4مندرجہ ذیل صورت حال میں آلودگی ہو سکتی ہے:
import java.util.ArrayList;
import java.util.List;

public class Main {

   static List<String> makeHeapPollution() {
       List numbers = new ArrayList<Number>();
       numbers.add(1);
       List<String> strings = numbers;
       strings.add("");
       return strings;
   }

   public static void main(String[] args) {

       List<String> stringsWithHeapPollution = makeHeapPollution();

       System.out.println(stringsWithHeapPollution.get(0));
   }
}
کنسول آؤٹ پٹ:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
سادہ الفاظ میں، ڈھیر کی آلودگی ایک ایسی صورت حال ہے جس میں قسم 1 کی اشیاء کو ڈھیر پر ہونا چاہیے А، لیکن قسم کی اشیاء وہیں ختم ہو جاتی ہیں B، قسم کی حفاظتی غلطیوں کی وجہ سے۔ ہماری مثال میں ایسا ہی ہوتا ہے۔ پہلے ہم نے Raw متغیر بنایا numbersاور اسے ایک عام مجموعہ تفویض کیا ArrayList<Number>۔ اس کے بعد ہم نے وہاں نمبر شامل کیا 1۔
List<String> strings = numbers;
اس لائن میں، کمپائلر نے وارننگ جاری کر کے ممکنہ غلطیوں کے بارے میں ہمیں متنبہ کرنے کی کوشش کی " Unchecked اسائنمنٹ... "، لیکن ہم نے اسے نظر انداز کر دیا۔ نتیجے کے طور پر، ہمارے پاس قسم کا ایک عام متغیر ہے List<String>، جو قسم کے عام مجموعہ کی طرف اشارہ کرتا ہے ArrayList<Number>۔ یہ صورت حال واضح طور پر مصیبت کا باعث بن سکتی ہے! ایسا ہی ہوتا ہے۔ اپنے نئے متغیر کا استعمال کرتے ہوئے، ہم مجموعہ میں ایک تار شامل کرتے ہیں۔ ڈھیر آلودہ تھا - ہم نے پہلے ایک نمبر اور پھر ٹائپ کردہ مجموعہ میں ایک تار شامل کیا۔ کمپائلر نے ہمیں خبردار کیا، لیکن ہم نے اس کی وارننگ کو نظر انداز کر دیا، ClassCastExceptionپروگرام کے چلنے کے دوران ہی نتائج موصول ہوئے۔ اس کا اس سے کیا تعلق ہے varargs؟ جنرک کے ساتھ استعمال varargsآسانی سے ڈھیر کی آلودگی کا باعث بن سکتا ہے۔ یہاں ایک سادہ مثال ہے:
import java.util.Arrays;
import java.util.List;

public class Main {

   static void makeHeapPollution(List<String>... stringsLists) {
       Object[] array = stringsLists;
       List<Integer> numbersList = Arrays.asList(66,22,44,12);

       array[0] = numbersList;
       String str = stringsLists[0].get(0);
   }

   public static void main(String[] args) {

       List<String> cars1 = Arrays.asList("Ford", "Fiat", "Kia");
       List<String> cars2 = Arrays.asList("Ferrari", "Bugatti", "Zaporozhets");

       makeHeapPollution(cars1, cars2);
   }
}
یہاں کیا ہو رہا ہے؟ قسم مٹانے کی وجہ سے، ہماری پیرامیٹر شیٹس (ہم سہولت کے لیے انہیں "لسٹوں" کے بجائے "شیٹس" کہیں گے) یہ ہیں -
List<String>...stringsLists
- شیٹس کی ایک صف میں بدل جائے گا - List[]ایک نامعلوم قسم کے ساتھ (یہ نہ بھولیں کہ تالیف کے نتیجے میں ورارگز ایک باقاعدہ صف میں بدل جاتا ہے)۔ Object[] arrayاس کی وجہ سے، ہم طریقہ کی پہلی لائن میں کسی متغیر کو آسانی سے ایک اسائنمنٹ بنا سکتے ہیں - اقسام کو ہماری شیٹس سے مٹا دیا گیا ہے! اور اب ہمارے پاس قسم کا ایک متغیر ہے Object[]، جہاں ہم کچھ بھی شامل کر سکتے ہیں - جاوا میں موجود تمام اشیاء اس سے وراثت میں ملتی ہیں Object! ابھی ہمارے پاس صرف سٹرنگ شیٹس کی ایک صف ہے۔ لیکن اقسام کے استعمال اور مٹانے کی بدولت varargs، ہم آسانی سے ان میں نمبروں کی شیٹ شامل کر سکتے ہیں، جو ہم کرتے ہیں۔ نتیجے کے طور پر، ہم مختلف اقسام کی اشیاء کو ملا کر ڈھیر کو آلودہ کرتے ہیں۔ ClassCastExceptionسرنی سے سٹرنگ کو پڑھنے کی کوشش کرتے وقت نتیجہ وہی مستثنیٰ ہوگا ۔ کنسول آؤٹ پٹ:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
یہ وہ غیر متوقع نتائج ہیں جو بظاہر سادہ طریقہ کار کے استعمال کے نتیجے میں ہو سکتے ہیں varargs:) اور یہیں پر ہمارا آج کا لیکچر اختتام پذیر ہوتا ہے۔ چند مسائل کو حل کرنا نہ بھولیں، اور اگر آپ کے پاس وقت اور توانائی باقی ہے تو اضافی لٹریچر کا مطالعہ کریں۔ " موثر جاوا " خود نہیں پڑھے گا! :) ملتے ہیں!
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION