CodeGym /جاوا بلاگ /Random-SD /varargs استعمال ڪندي جڏهن generics سان ڪم ڪرڻ
John Squirrels
سطح
San Francisco

varargs استعمال ڪندي جڏهن generics سان ڪم ڪرڻ

گروپ ۾ شايع ٿيل
سلام اڄ جي سبق ۾، اسين generics جو مطالعو جاري رکنداسين. جيئن ته ائين ٿئي ٿو، اهو هڪ وڏو موضوع آهي، پر ان کان بچڻ جي ڪا به ضرورت ناهي - اها ٻولي جو هڪ انتهائي اهم حصو آهي :) جڏهن توهان Oracle ڊاڪيومينٽيشن کي جنريڪس تي پڙهو ٿا يا آن لائن سبق پڙهو ٿا، توهان کي اصطلاحن تي نظر اينديون غير قابل تصديق قسمون ۽ قابل تجديد قسم . ريفائيبل قسم ھڪڙو قسم آھي جنھن لاء معلومات مڪمل طور تي دستياب آھي رن ٽائم تي. جاوا ۾، اهڙن قسمن ۾ شامل آهن پرائمري، خام قسم، ۽ غير عام قسم. ان جي ابتڙ، غير ريفائيبل قسم جا قسم آهن جن جي معلومات ختم ٿي ويندي آهي ۽ رن ٽائم تي ناقابل رسائي ٿي ويندي آهي. جيئن ته اهو ٿئي ٿو، اهي عام آهن - 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>(), // This is okay
               "Leonardo da Vinci",
               "Vasco de Gama"
       );

       // but here we get a warning
       addAll(new ArrayList<Pair<String, String>>(),
               new Pair<String, String>("Leonardo", "da Vinci"),
               new Pair<String, String>("Vasco", "de Gama")
       );
   }
}
طريقو addAll()انپٽ جي طور تي وٺندو آهي a List<E>۽ ڪنهن به شئي جو تعداد E، ۽ پوء اهو انهن سڀني شين کي لسٽ ۾ شامل ڪري ٿو. طريقي ۾ main()، اسان کي اسان جو addAll()طريقو ٻه ڀيرا سڏين ٿا. پهرين صورت ۾، اسان ٻه عام اسٽرنگ شامل ڪندا آهيون List. هتي هر شي ترتيب ۾ آهي. ٻئي صورت ۾، اسان ٻه Pair<String, String>شيون شامل ڪيون ٿا List. پر هتي اسان کي غير متوقع طور تي هڪ ڊيڄاريندڙ ملي ٿي:

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>هڪ غير ريفائيبل قسم آهي. تاليف جي دوران، قسم جي دلائل بابت سڀ معلومات (<String، String>) ختم ٿي ويندي آهي. جاوا ۾ غير ريفائيبل قسم جي صفن کي ٺاهڻ جي اجازت ناهي . توھان ھي ڏسي سگھو ٿا جيڪڏھن توھان ڪوشش ڪريو دستي طور ھڪڙو جوڙو ٺاھيو<String, String> array
public static void main(String[] args) {

   // Compilation error Generic array creation
  Pair<String, String>[] array = new Pair<String, String>[10];
}
سبب واضح آهي: قسم جي حفاظت. جيئن توهان کي ياد هوندو، جڏهن هڪ صف ٺاهيندي، توهان کي يقيني طور تي وضاحت ڪرڻ جي ضرورت آهي ته ڪهڙيون شيون (يا پرائمري) سرن کي ذخيرو ڪندو.
int array[] = new int[10];
اسان جي پوئين سبقن مان هڪ ۾، اسان تفصيل سان ٽائپ ايريچر جو جائزو ورتو. انهي صورت ۾، ٽائيپ erasure اسان کي ان معلومات کي وڃائڻ جو سبب بڻائيندو آهي جيڪي Pairشيون جوڙا ذخيرو ڪن ٿيون <String, String>. صف ٺاهڻ غير محفوظ هوندو. جڏهن طريقن کي استعمال ڪندي جنهن ۾ varargs ۽ generics شامل آهن، ياد رکڻ جي پڪ ڪريو ته قسم ختم ڪرڻ ۽ اهو ڪيئن ڪم ڪري ٿو. جيڪڏهن توهان مڪمل طور تي ان ڪوڊ جي باري ۾ پڪ ڄاڻو ٿا جيڪو توهان لکيو آهي ۽ ڄاڻو ٿا ته اهو ڪنهن به مسئلي جو سبب نه ٿيندو، توهان تشريح استعمال ڪندي varargs سان لاڳاپيل ڊيڄاريندڙن کي بند ڪري سگهو ٿا @SafeVarargs.
@SafeVarargs
public static <E> void addAll(List<E> list, E... array) {

   for (E element : array) {
       list.add(element);
   }
}
جيڪڏھن توھان ھن تشريح کي پنھنجي طريقي ۾ شامل ڪيو، اھو ڊيڄاريندڙ جيڪو اسان اڳ ۾ ڏٺو ھو، ظاهر نه ٿيندو. هڪ ٻيو مسئلو اهو ٿي سگهي ٿو جڏهن عام طور تي varargs استعمال ڪندي هيپ آلودگي آهي. عام طور تي ڪم ڪرڻ دوران varargs استعمال ڪرڻ - 3هيپ آلودگي هيٺين صورتحال ۾ ٿي سگهي ٿي:
import java.util.ArrayList;
import java.util.List;

public class Main {

   static List<String> polluteHeap() {
       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 = polluteHeap();

       System.out.println(stringsWithHeapPollution.get(0));
   }
}
ڪنسول آئوٽ:

Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
سادي اصطلاحن ۾، هيپ آلودگي اها آهي جڏهن قسم جون شيون Aڍير ۾ هجن، پر قسم جون شيون Bاتي ختم ٿي وينديون آهن قسم جي حفاظت سان لاڳاپيل غلطين جي ڪري. اسان جي مثال ۾، ائين ئي ٿئي ٿو. پهرين، اسان خام numbersمتغير ٺاهيو ۽ ArrayList<Number>ان کي هڪ عام مجموعي ( ) لڳايو. ان کان پوء اسان ان نمبر کي 1گڏ ڪرڻ ۾ شامل ڪيو.
List<String> strings = numbers;
هن لائن تي، مرتب ڪندڙ اسان کي " اڻ چيڪ ٿيل اسائنمينٽ... " وارننگ جاري ڪري ممڪنن غلطين کان ڊيڄارڻ جي ڪوشش ڪئي، پر اسان ان کي نظرانداز ڪيو. اسان ھڪڙي قسم جي عام متغير سان ختم ڪريون ٿا List<String>جيڪو ھڪڙي قسم جي عام مجموعي ڏانھن اشارو ڪري ٿو ArrayList<Number>. واضح طور تي، هي صورتحال مصيبت پيدا ڪري سگهي ٿي! ۽ ائين ئي ٿئي ٿو. اسان جي نئين متغير کي استعمال ڪندي، اسان گڏ ڪرڻ لاء هڪ اسٽرنگ شامل ڪندا آهيون. اسان وٽ ھاڻي آلودگي جو ڍير آھي - اسان ھڪڙو نمبر شامل ڪيو ۽ پوءِ ھڪڙي تار کي پيراميٽرائزڊ ڪليڪشن ۾. مرتب ڪندڙ اسان کي خبردار ڪيو، پر اسان ان جي خبرداري کي نظرانداز ڪيو. نتيجي طور، اسان ClassCastExceptionصرف حاصل ڪندا آهيون جڏهن پروگرام هلندي آهي. تنهن ڪري هن جو varargs سان ڇا تعلق آهي؟ generics سان varargs استعمال ڪرڻ آساني سان آلودگي کي رسي سگهي ٿو. هتي هڪ سادي مثال آهي:
import java.util.Arrays;
import java.util.List;

public class Main {

   static void polluteHeap(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");

       polluteHeap(cars1, cars2);
   }
}
هتي ڇا ٿي رهيو آهي؟ قسم erasure جي ڪري، اسان جي variable-لمبائي دليل
List<String>...stringsLists
فهرستن جي هڪ صف بڻجي وڃي ٿي، يعني List[]اڻڄاتل قسم جي شين جي (اهو نه وساريو ته varargs تاليف دوران باقاعده صف ۾ تبديل ٿي وڃي ٿي). انهي جي ڪري، اسان ان کي آساني سان ترتيب ڏئي سگھون ٿا Object[] arrayمتغير کي طريقي جي پهرين لائن ۾ - اسان جي لسٽن ۾ شيون جو قسم ختم ڪيو ويو آهي! ۽ ھاڻي اسان وٽ ھڪڙو Object[]متغير آھي، جنھن ۾ اسين ڪجھ به شامل ڪري سگھون ٿا، ڇو ته جاوا ۾ سڀ شيون وارث آھن Object! پهرين ۾، اسان وٽ صرف اسٽرنگ جي فهرستن جي هڪ صف آهي. پر مهرباني ڪري ٽائپ erasure ۽ اسان جي 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