JavaRush /جاوا بلاگ /Random-UR /جاوا میں عام کیا ہیں؟

جاوا میں عام کیا ہیں؟

گروپ میں شائع ہوا۔
ہیلو! آج ہم generics کے بارے میں بات کریں گے۔ مجھے یہ کہنا ضروری ہے کہ آپ بہت سی نئی چیزیں سیکھیں گے! نہ صرف یہ بلکہ اگلے چند لیکچرز جنرک کے لیے وقف ہوں گے۔ جاوا میں عام کیا ہیں - 1 لہذا، اگر یہ موضوع آپ کے لیے دلچسپ ہے، تو آپ خوش قسمت ہیں: آج آپ کو جنرک کی خصوصیات کے بارے میں بہت کچھ سیکھنے کو ملے گا۔ ٹھیک ہے، اگر نہیں، تو پرسکون ہو جاؤ اور آرام کرو! :) یہ ایک بہت اہم موضوع ہے اور آپ کو اسے جاننے کی ضرورت ہے۔ آئیے ایک سادہ سے شروع کریں: "کیا" اور "کیوں"۔ generics کیا ہیں؟ جنرکس پیرامیٹر والی قسمیں ہیں۔ عام تخلیق کرتے وقت، آپ نہ صرف اس کی قسم، بلکہ ڈیٹا کی قسم بھی بتاتے ہیں جس کے ساتھ اسے کام کرنا چاہیے۔ میرے خیال میں سب سے واضح مثال آپ کے ذہن میں آ چکی ہے - یہ ہے ArrayList! یہاں یہ ہے کہ ہم اسے پروگرام میں عام طور پر کیسے بناتے ہیں:
import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<String> myList1 = new ArrayList<>();
       myList1.add("Test String 1");
       myList1.add("Test String 2");
   }
}
جیسا کہ آپ اندازہ لگا سکتے ہیں، فہرست کی خاصیت یہ ہے کہ اس میں ہر چیز کو "اسٹف" کرنا ممکن نہیں ہوگا: یہ صرف اشیاء کے ساتھ کام کرتی ہے String۔ اب آئیے جاوا کی تاریخ میں ایک مختصر سیر کرتے ہیں اور اس سوال کا جواب دینے کی کوشش کرتے ہیں: "کیوں؟" ایسا کرنے کے لیے، ہم خود ArrayList کلاس کا ایک آسان ورژن لکھیں گے۔ ہماری فہرست صرف اندرونی صف میں ڈیٹا شامل کر سکتی ہے اور یہ ڈیٹا وصول کر سکتی ہے:
public class MyListClass {

   private Object[] data;
   private int count;

   public MyListClass() {
       this.data = new Object[10];
       this.count = 0;
   }

   public void add(Object o) {
       this.data[count] = o;
       count++;
   }

   public Object[] getData() {
       return data;
   }
}
ہم کہتے ہیں کہ ہم چاہتے ہیں کہ ہماری فہرست صرف نمبروں کو محفوظ کرے Integer۔ ہمارے پاس جنرک نہیں ہے۔ Integerہم واضح طور پر o میں چیک کی مثال کی وضاحت نہیں کر سکتے add()۔ تب ہماری پوری کلاس صرف کے لیے موزوں ہوگی Integer، اور ہمیں دنیا میں موجود تمام ڈیٹا کی اقسام کے لیے ایک ہی کلاس لکھنی ہوگی! ہم اپنے پروگرامرز پر بھروسہ کرنے کا فیصلہ کرتے ہیں اور کوڈ میں صرف ایک تبصرہ چھوڑتے ہیں تاکہ وہ وہاں کوئی غیر ضروری چیز شامل نہ کریں:
//use it ONLY with Integer data type
public void add(Object o) {
   this.data[count] = o;
   count++;
}
پروگرامرز میں سے ایک نے یہ تبصرہ چھوٹ دیا اور نادانستہ طور پر فہرست میں تاروں کے ساتھ ملا ہوا نمبر ڈالنے کی کوشش کی، اور پھر ان کی رقم کا حساب لگایا:
public class Main {

   public static void main(String[] args) {

       MyListClass list = new MyListClass();
       list.add(100);
       list.add(200);
       list.add("Lolkek");
       list.add("Shalala");

       Integer sum1 = (Integer) list.getData()[0] + (Integer) list.getData()[1];
       System.out.println(sum1);

       Integer sum2 = (Integer) list.getData()[2] + (Integer) list.getData()[3];
       System.out.println(sum2);
   }
}
کنسول آؤٹ پٹ: تھریڈ "main" java.lang.ClassCastException میں 300 استثناء: java.lang.String کو java.lang.Integer پر Main.main(Main.java:14) پر کاسٹ نہیں کیا جا سکتا۔ اس صورت حال میں سب سے خراب کیا ہے؟ پروگرامر کی عدم توجہی سے دور۔ سب سے بری بات یہ ہے کہ غلط کوڈ ہمارے پروگرام میں ایک اہم جگہ پر ختم ہوا اور کامیابی سے مرتب ہوا ۔ اب ہم غلطی کو کوڈنگ کے مرحلے پر نہیں بلکہ صرف جانچ کے مرحلے پر دیکھیں گے (اور یہ بہترین صورت میں ہے!) ترقی میں بعد میں کیڑے ٹھیک کرنے میں بہت زیادہ لاگت آتی ہے - پیسہ اور وقت دونوں۔ یہ خاص طور پر جنرک کا فائدہ ہے: ایک عام کلاس بدقسمت پروگرامر کو فوری طور پر غلطی کا پتہ لگانے کی اجازت دے گی۔ کوڈ صرف مرتب نہیں کرے گا!
import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

       List<Integer> myList1 = new ArrayList<>();

       myList1.add(100);
       myList1.add(100);
       myList1.add("Lolkek");//error!
       myList1.add("Shalala");//error!
   }
}
پروگرامر فوری طور پر "اپنے ہوش میں آجائے گا" اور فوری طور پر خود کو درست کر لے گا۔ ویسے Listاس قسم کی خرابی دیکھنے کے لیے ہمیں اپنی کلاس بنانے کی ضرورت نہیں تھی۔ بس ٹائپ بریکٹ ( <Integer>) کو باقاعدہ ArrayList سے ہٹا دیں!
import java.util.ArrayList;
import java.util.List;

public class Main {

   public static void main(String[] args) {

      List list = new ArrayList();

      list.add(100);
      list.add(200);
      list.add("Lolkek");
      list.add("Shalala");

       System.out.println((Integer) list.get(0) + (Integer) list.get(1));
       System.out.println((Integer) list.get(2) + (Integer) list.get(3));
   }
}
کنسول آؤٹ پٹ: تھریڈ "main" java.lang.ClassCastException میں 300 استثناء: java.lang.String کو java.lang.Integer پر Main.main(Main.java:16) پر کاسٹ نہیں کیا جا سکتا، یعنی، یہاں تک کہ "مقامی" ٹولز کا استعمال کرتے ہوئے جاوا، آپ یہ غلطی کر سکتے ہیں اور ایک غیر محفوظ مجموعہ بنا سکتے ہیں۔ تاہم، اگر ہم اس کوڈ کو IDEa میں چسپاں کرتے ہیں، تو ہمیں ایک انتباہ نظر آتا ہے: " java.util.List کی خام قسم کے ممبر کے طور پر شامل کرنے کے لیے غیر چیک شدہ کال " یہ ہمیں بتاتا ہے کہ کسی عنصر کو شامل کرتے وقت کچھ غلط ہو سکتا ہے۔ generics کے بغیر مجموعہ اس طرح نہیں. لیکن جملے "خام قسم" کا کیا مطلب ہے؟ لفظی ترجمہ بالکل درست ہوگا - " کچی قسم " یا " گندی قسمRaw typeایک عام کلاس ہے جس سے اس کی قسم کو ہٹا دیا گیا ہے۔ دوسرے الفاظ میں، List myList1یہ ہے Raw type. اس کے برعکس ایک عام کلاس raw typeہے generic type(جسے کلاس کے نام سے بھی جانا جاتا ہے parameterized type)، ایک قسم کی تفصیلات کے ساتھ صحیح طریقے سے تخلیق کیا گیا ہے۔ مثال کے طور پر، List<String> myList1. آپ کا سوال ہو سکتا ہے: اسے استعمال کرنے کی اجازت کیوں ہے raw types؟ وجہ سادہ ہے۔ جاوا کے تخلیق کاروں نے زبان میں تعاون چھوڑ دیا raw typesتاکہ مطابقت کے مسائل پیدا نہ ہوں۔ جاوا 5.0 کے جاری ہونے تک (اس ورژن میں پہلی بار جنرکس نمودار ہوئے)، استعمال کرتے ہوئے بہت سارے کوڈ پہلے ہی لکھے جا چکے تھے raw types۔ اس لیے یہ امکان آج بھی موجود ہے۔ ہم جوشوا بلوچ کی کلاسک کتاب "Effective Java" کا ذکر ایک سے زیادہ بار لیکچرز میں کر چکے ہیں۔ زبان کے تخلیق کاروں میں سے ایک کے طور پر، انہوں نے کتاب میں استعمال raw typesاور استعمال کے موضوع کو نظر انداز نہیں کیا generic types۔ جاوا میں عام کیا ہیں - 2اس کتاب کے باب 23 کا ایک بہت ہی فصیح عنوان ہے: "نئے کوڈ میں خام اقسام کا استعمال نہ کریں۔" یہ وہ چیز ہے جسے آپ کو یاد رکھنے کی ضرورت ہے۔ عام کلاسز کا استعمال کرتے وقت، انہیں کبھی بھی generic typeمیں تبدیل نہ کریں raw type۔

ٹائپ شدہ طریقے

جاوا آپ کو انفرادی طریقوں کو ٹائپ کرنے کی اجازت دیتا ہے، نام نہاد عام طریقوں کو بناتا ہے۔ اس طرح کے طریقے کیوں آسان ہیں؟ سب سے پہلے، کیونکہ وہ آپ کو مختلف قسم کے پیرامیٹرز کے ساتھ کام کرنے کی اجازت دیتے ہیں۔ اگر ایک ہی منطق کو مختلف اقسام پر محفوظ طریقے سے لاگو کیا جا سکتا ہے، تو ایک عام طریقہ ایک بہترین حل ہے۔ آئیے ایک مثال دیکھتے ہیں۔ ہم کہتے ہیں کہ ہمارے پاس کسی قسم کی فہرست ہے myList1۔ ہم اس سے تمام اقدار کو ہٹانا چاہتے ہیں، اور تمام خالی جگہوں کو ایک نئی قدر سے بھرنا چاہتے ہیں۔ عام طریقہ کے ساتھ ہماری کلاس اس طرح نظر آئے گی:
public class TestClass {

   public static <T> void fill(List<T> list, T val) {
       for (int i = 0; i < list.size(); i++)
           list.set(i, val);
   }

   public static void main(String[] args) {

       List<String> strings = new ArrayList<>();
       strings.add("Старая строка 1");
       strings.add("Старая строка 2");
       strings.add("Старая строка 3");

       fill(strings, "Новая строка");

       System.out.println(strings);

       List<Integer> numbers = new ArrayList<>();
       numbers.add(1);
       numbers.add(2);
       numbers.add(3);

       fill(numbers, 888);
       System.out.println(numbers);
   }
}
نحو پر توجہ دیں، یہ تھوڑا سا غیر معمولی لگتا ہے:
public static <T> void fill(List<T> list, T val)
واپسی کی قسم <T> سے پہلے ہے، جو ایک عام طریقہ کی نشاندہی کرتا ہے۔ اس صورت میں، طریقہ ان پٹ کے طور پر 2 پیرامیٹرز لیتا ہے: اشیاء T کی ایک فہرست اور ایک اور الگ آبجیکٹ T۔ <T> کا استعمال کرتے ہوئے، طریقہ کی ٹائپنگ حاصل کی جاتی ہے: ہم وہاں تاروں کی فہرست اور نمبر پاس نہیں کر سکتے۔ تاروں اور تاروں کی فہرست، نمبروں اور نمبروں کی فہرست، ہماری اشیاء کی فہرست Catاور ایک اور چیز Cat- یہی واحد راستہ ہے۔ طریقہ main()واضح طور پر ظاہر کرتا ہے کہ یہ طریقہ fill()مختلف قسم کے ڈیٹا کے ساتھ آسانی سے کام کرتا ہے۔ سب سے پہلے، یہ ان پٹ کے طور پر سٹرنگز اور سٹرنگ کی فہرست لیتا ہے، اور پھر نمبروں اور نمبروں کی فہرست۔ کنسول آؤٹ پٹ: [نیو لائن، نیو لائن، نیو لائن] [888، 888، 888] تصور کریں کہ کیا fill()ہمیں 30 مختلف کلاسوں کے لیے طریقہ کار کی منطق کی ضرورت ہے، اور ہمارے پاس عام طریقے نہیں ہیں۔ ہمیں 30 بار ایک ہی طریقہ لکھنے پر مجبور کیا جائے گا، صرف مختلف ڈیٹا کی اقسام کے لیے! لیکن عام طریقوں کی بدولت، ہم اپنے کوڈ کو دوبارہ استعمال کر سکتے ہیں! :)

ٹائپ شدہ کلاسز

آپ جاوا میں فراہم کردہ عام کلاسوں کو نہ صرف استعمال کر سکتے ہیں، بلکہ اپنی تخلیق بھی کر سکتے ہیں! یہاں ایک سادہ مثال ہے:
public class Box<T> {

   private T t;

   public void set(T t) {
       this.t = t;
   }

   public T get() {
       return t;
   }

   public static void main(String[] args) {

       Box<String> stringBox = new Box<>();

       stringBox.set("Старая строка");
       System.out.println(stringBox.get());
       stringBox.set("Новая строка");

       System.out.println(stringBox.get());

       stringBox.set(12345);//ошибка компиляции!
   }
}
ہماری کلاس Box<T>("باکس") ٹائپ کی گئی ہے۔ تخلیق کے دوران اس کو ڈیٹا کی قسم ( ) تفویض کرنے کے بعد <T>، ہم اس میں دوسری قسم کی اشیاء نہیں رکھ سکیں گے۔ یہ مثال میں دیکھا جا سکتا ہے۔ بناتے وقت، ہم نے واضح کیا کہ ہمارا آبجیکٹ تاروں کے ساتھ کام کرے گا:
Box<String> stringBox = new Box<>();
اور جب کوڈ کی آخری لائن میں ہم نمبر 12345 کو باکس کے اندر ڈالنے کی کوشش کرتے ہیں تو ہمیں ایک کمپلیشن ایرر ملتا ہے! بالکل اسی طرح، ہم نے اپنی عام کلاس بنائی! :) یہ آج ہمارا لیکچر ختم کرتا ہے۔ لیکن ہم جنرک کو الوداع نہیں کہہ رہے ہیں! اگلے لیکچرز میں ہم مزید جدید خصوصیات کے بارے میں بات کریں گے، لہذا الوداع مت کہو! ) آپ کی تعلیم میں اچھی قسمت! :)
تبصرے
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION