JavaRush /جاوا بلاگ /Random-SD /جاوا ۾ عڪس - استعمال جا مثال

جاوا ۾ عڪس - استعمال جا مثال

گروپ ۾ شايع ٿيل
توهان شايد روزمره جي زندگيء ۾ "عڪس" جي تصور ۾ آيا هوندا. عام طور تي هي لفظ پنهنجو پاڻ کي پڙهڻ جي عمل ڏانهن اشارو ڪري ٿو. پروگرامنگ ۾، ان جو هڪ ئي مطلب آهي - اهو هڪ پروگرام جي باري ۾ ڊيٽا کي جانچڻ لاء هڪ ميکانيزم آهي، انهي سان گڏ ان جي عمل جي دوران پروگرام جي جوڙجڪ ۽ رويي کي تبديل ڪرڻ. هتي اهم شيء اها آهي ته اهو رن ٽائيم تي ڪيو ويندو آهي، نه گڏ ڪرڻ واري وقت تي. پر رن ​​ٽائم تي ڪوڊ کي ڇو جانچيو؟ توھان اڳ ۾ ئي ڏسندا آھيو:/ Reflection استعمال ڪرڻ جا مثال - 1عڪس جو خيال ھڪڙي سبب لاءِ فوري طور تي واضح نه ٿي سگھي ٿو: ھن لمحي تائين، توھان ھميشه ڄاڻو ٿا ڪلاس جيڪي توھان ڪم ڪري رھيا ھئا. خير، مثال طور، توهان هڪ ڪلاس لکي سگهو ٿا Cat:
package learn.javarush;

public class Cat {

   private String name;
   private int age;

   public Cat(String name, int age) {
       this.name = name;
       this.age = age;
   }

   public void sayMeow() {

       System.out.println("Meow!");
   }

   public void jump() {

       System.out.println("Jump!");
   }

   public String getName() {
       return name;
   }

   public void setName(String name) {
       this.name = name;
   }

   public int getAge() {
       return age;
   }

   public void setAge(int age) {
       this.age = age;
   }

@Override
public String toString() {
   return "Cat{" +
           "name='" + name + '\'' +
           ", age=" + age +
           '}';
}

}
توهان ان بابت سڀ ڪجهه ڄاڻو ٿا، توهان ڏسو ته ان جا ڪهڙا شعبا ۽ طريقا آهن. يقينا توهان هڪ وراثت سسٽم ٺاهي سگهو ٿا هڪ عام طبقي سان سهولت لاء Animal، جيڪڏهن اوچتو پروگرام کي ٻين طبقن جي جانورن جي ضرورت هجي. اڳي، اسان هڪ ويٽرنري ڪلينڪ ڪلاس پڻ ٺاهيو جنهن ۾ توهان هڪ والدين اعتراض پاس ڪري سگهو ٿا Animal، ۽ پروگرام جانور جو علاج ڪندو ان تي منحصر آهي ته اهو ڪتو آهي يا ٻلي. جيتوڻيڪ اهي ڪم ڏاڍا سادا نه آهن، پر پروگرام سکي ٿو سموري معلومات جيڪا ان کي ڪلاسن بابت گهربل آهي مرتب ڪرڻ وقت. تنهن ڪري، جڏهن توهان هڪ طريقي سان main()هڪ اعتراض کي جانورن جي ڪلينڪ ڪلاس جي طريقن ڏانهن منتقل ڪيو Cat، پروگرام اڳ ۾ ئي ڄاڻي ٿو ته هي هڪ ٻلي آهي، نه ڪتو. هاڻي اچو ته تصور ڪريون ته اسان کي هڪ ٻيو ڪم درپيش آهي. اسان جو مقصد ڪوڊ اينالائيزر لکڻ آهي. CodeAnalyzerاسان کي ھڪڙي ھڪڙي طريقي سان ھڪڙي ڪلاس ٺاهڻ جي ضرورت آھي - void analyzeClass(Object o). اهو طريقو گهرجي:
  • اهو طئي ڪيو ته ڪهڙي ڪلاس ۾ اعتراض پاس ڪيو ويو ۽ ڪنسول ۾ ڪلاس جو نالو ڏيکاريو؛
  • هن طبقي جي سڀني شعبن جا نالا مقرر ڪريو، جن ۾ خانگي شامل آهن، ۽ انهن کي ڪنسول ۾ ڏيکاريو؛
  • هن طبقي جي سڀني طريقن جا نالا مقرر ڪريو، جن ۾ خانگي شامل آهن، ۽ انهن کي ڪنسول ۾ ڏيکاري ٿو.
اهو ڪجهه هن طرح نظر ايندو:
public class CodeAnalyzer {

   public static void analyzeClass(Object o) {

       //Вывести название класса, к которому принадлежит an object o
       //Вывести названия всех переменных этого класса
       //Вывести названия всех методов этого класса
   }

}
هاڻي هن مسئلي ۽ باقي مسئلن جي وچ ۾ فرق نظر اچي ٿو جيڪو توهان اڳ ۾ حل ڪيو هو. انهي حالت ۾، مشڪل حقيقت ۾ ڪوڙ آهي ته نه توهان کي ۽ نه ئي پروگرام کي خبر آهي ته ڇا طريقي سان منتقل ڪيو ويندو analyzeClass(). توهان هڪ پروگرام لکندا آهيو، ٻيا پروگرامر ان کي استعمال ڪرڻ شروع ڪندا، جيڪي هن طريقي ۾ ڪا به شيءِ پاس ڪري سگهن ٿا - ڪنهن به معياري جاوا ڪلاس يا ڪنهن به ڪلاس جو انهن لکيو آهي. هن طبقي ۾ ڪي به تعداد ۾ متغير ۽ طريقا ٿي سگهن ٿا. ٻين لفظن ۾، هن صورت ۾ اسان (۽ اسان جي پروگرام) کي ڪا به خبر ناهي ته اسان ڪهڙن طبقن سان ڪم ڪنداسين. ۽ اڃا تائين، اسان کي هن مسئلي کي حل ڪرڻ گهرجي. ۽ هتي معياري جاوا لائبريري اسان جي مدد لاءِ اچي ٿي - Java Reflection API. Reflection API هڪ طاقتور ٻولي خصوصيت آهي. سرڪاري Oracle دستاويزن ۾ چيو ويو آهي ته هي ميکانيزم صرف تجربيڪار پروگرامرز پاران استعمال ڪرڻ جي سفارش ڪئي وئي آهي جيڪي چڱي طرح سمجهي رهيا آهن ته اهي ڇا ڪري رهيا آهن. توهان جلد ئي سمجھندا سين ڇو ته اسان کي اوچتو اهڙيون ڊيڄاريندڙ اڳواٽ ۾ ڏنيون ويون آهن :) هتي هڪ فهرست آهي ڇا ڪري سگهجي ٿو Reflection API استعمال ڪندي:
  1. ڪنهن شئي جي درجي کي ڳولهيو/ متعين ڪريو.
  2. ڪلاس موڊيفائرز، فيلڊز، طريقا، مستقل، تعمير ڪندڙ ۽ سپر ڪلاسز بابت ڄاڻ حاصل ڪريو.
  3. معلوم ڪريو ته ڪهڙا طريقا لاڳو ٿيل انٽرفيس/انٽرفيس سان تعلق رکن ٿا.
  4. ھڪڙي ڪلاس جو ھڪڙو مثال ٺاھيو جڏھن ڪلاس جو نالو نامعلوم آھي جيستائين پروگرام تي عمل نه ڪيو وڃي.
  5. حاصل ڪريو ۽ نالي سان هڪ اعتراض فيلڊ جي قيمت مقرر ڪريو.
  6. نالي سان هڪ اعتراض جي طريقي کي ڪال ڪريو.
متاثر ڪندڙ فهرست، ها؟ :) توجهه ڏيو:ريفريڪشن ميکانيزم اهو سڀ ڪجهه ڪرڻ جي قابل آهي ”اُڏام تي“ قطع نظر ته اسان پنهنجي ڪوڊ اينالائيزر وٽ ڪهڙي به طبقي جو اعتراض پاس ڪريون! اچو ته مثالن سان Reflection API جي صلاحيتن کي ڏسو.

ڪنهن شئي جي درجي کي ڪيئن ڳولهيو / طئي ڪيو وڃي

اچو ته بنيادي ڳالهين سان شروع ڪريون. جاوا جي موٽڻ واري ميڪانيزم ۾ داخل ٿيڻ جو نقطو آهي Class. ها، اهو واقعي مضحکہ خیز لڳي ٿو، پر اهو ئي آهي جنهن لاءِ عڪس آهي :) هڪ ڪلاس استعمال ڪندي Class، اسان سڀ کان پهريان اسان جي طريقي سان منظور ڪيل ڪنهن به شئي جي ڪلاس کي طئي ڪندا آهيون. اچو ته اها ڪوشش ڪريون:
import learn.javarush.Cat;

public class CodeAnalyzer {

   public static void analyzeClass(Object o) {
       Class clazz = o.getClass();
       System.out.println(clazz);
   }

   public static void main(String[] args) {

       analyzeClass(new Cat("Barsik", 6));
   }
}
ڪنسول آئوٽ:

class learn.javarush.Cat
ٻن ڳالهين تي ڌيان ڏيو. پهرين، اسان عمدي طور ڪلاس کي Catالڳ پيڪيج ۾ رکيو، learn.javarush;هاڻي توهان ڏسي سگهو ٿا ته اهو getClass()ڪلاس جو پورو نالو واپس ڪري ٿو. ٻيو، اسان نالو رکيو اسان جي variable clazz. ٿورڙو عجيب لڳي ٿو. يقينا، ان کي "ڪلاس" سڏيو وڃي، پر "ڪلاس" جاوا ٻوليء ۾ هڪ محفوظ لفظ آهي، ۽ مرتب ڪندڙ متغيرن کي ان طريقي سان سڏڻ جي اجازت نه ڏيندو. مون کي ان مان نڪرڻو پيو :) خير، خراب شروعات نه! اسان وٽ امکانات جي فهرست تي ٻيو ڇا آهي؟

ڪلاس ميڊيفائرز، فيلڊز، طريقا، مستقل، تعمير ڪندڙ ۽ سپر ڪلاس بابت معلومات ڪيئن حاصل ڪجي

اهو اڳ ۾ ئي وڌيڪ دلچسپ آهي! موجوده ڪلاس ۾ اسان وٽ ڪو به مستقل ۽ والدين طبقو ناهي. اچو ته ان کي مڪمل ڪرڻ لاء شامل ڪريو. اچو ته آسان ترين والدين ڪلاس ٺاهيون Animal:
package learn.javarush;
public class Animal {

   private String name;
   private int age;
}
۽ اچو ته Catوراثت شامل ڪريون Animal۽ هڪ مسلسل اسان جي طبقي ۾:
package learn.javarush;

public class Cat extends Animal {

   private static final String ANIMAL_FAMILY = "Семейство кошачьих";

   private String name;
   private int age;

   //...остальная часть класса
}
هاڻي اسان وٽ هڪ مڪمل سيٽ آهي! اچو ته ڪوشش ڪريون غور ڪرڻ جا امڪان :)
import learn.javarush.Cat;

import java.util.Arrays;

public class CodeAnalyzer {

   public static void analyzeClass(Object o) {
       Class clazz = o.getClass();
       System.out.println("Name класса: " + clazz);
       System.out.println("Поля класса: " + Arrays.toString(clazz.getDeclaredFields()));
       System.out.println("Родительский класс: " + clazz.getSuperclass());
       System.out.println("Методы класса: " +  Arrays.toString(clazz.getDeclaredMethods()));
       System.out.println("Конструкторы класса: " + Arrays.toString(clazz.getConstructors()));
   }

   public static void main(String[] args) {

       analyzeClass(new Cat("Barsik", 6));
   }
}
اهو آهي جيڪو اسان ڪنسول ۾ حاصل ڪريون ٿا:
Name класса: class learn.javarush.Cat
Поля класса: [private static final java.lang.String learn.javarush.Cat.ANIMAL_FAMILY, private java.lang.String learn.javarush.Cat.name, private int learn.javarush.Cat.age]
Родительский класс: class learn.javarush.Animal
Методы класса: [public java.lang.String learn.javarush.Cat.getName(), public void learn.javarush.Cat.setName(java.lang.String), public void learn.javarush.Cat.sayMeow(), public void learn.javarush.Cat.setAge(int), public void learn.javarush.Cat.jump(), public int learn.javarush.Cat.getAge()]
Конструкторы класса: [public learn.javarush.Cat(java.lang.String,int)]
اسان ڪلاس بابت تمام گهڻي تفصيلي ڄاڻ حاصل ڪئي! ۽ نه رڳو عوام بابت، پر نجي حصن بابت پڻ. توجهه ڏيو: private-variables پڻ لسٽ ۾ ڏيکاريل آھن. درحقيقت، طبقي جو "تجزيو" هن نقطي تي مڪمل سمجهي سگهجي ٿو: هاڻي، طريقي سان استعمال ڪندي، analyzeClass()اسان سڀ ڪجهه سکندا سين جيڪا ممڪن آهي. پر اهي سڀئي امڪان نه آهن جيڪي اسان وٽ آهن جڏهن عکاس سان ڪم ڪري رهيا آهيون. اچو ته پاڻ کي سادي مشاهدي تائين محدود نه رکون ۽ فعال عمل ڏانهن وڃو! :)

ڪلاس جو هڪ مثال ڪيئن ٺاهيو جيڪڏهن ڪلاس جو نالو اڻڄاتل آهي پروگرام تي عمل ٿيڻ کان اڳ

اچو ته ڊفالٽ ڪنسٽرڪٽر سان شروع ڪريون. اهو اڃا تائين اسان جي ڪلاس ۾ ناهي Cat، تنهنڪري اچو ته ان کي شامل ڪريو:
public Cat() {

}
ھتي اھو آھي ته ڪوڊ جھڙو نظر ايندو ھڪ اعتراض ٺاھڻ لاءِ Catعڪس (طريقو createCat()):
import learn.javarush.Cat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

   public static Cat createCat() throws IOException, IllegalAccessException, InstantiationException, ClassNotFoundException {

       BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
       String className = reader.readLine();

       Class clazz = Class.forName(className);
       Cat cat = (Cat) clazz.newInstance();

       return cat;
   }

public static Object createObject() throws Exception {

   BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
   String className = reader.readLine();

   Class clazz = Class.forName(className);
   Object result = clazz.newInstance();

   return result;
}

   public static void main(String[] args) throws IOException, IllegalAccessException, ClassNotFoundException, InstantiationException {
       System.out.println(createCat());
   }
}
ڪنسول ۾ داخل ڪريو:

learn.javarush.Cat
ڪنسول آئوٽ:

Cat{name='null', age=0}
هي هڪ غلطي ناهي: قدر name۽ ageڏيکاريل آهن ڪنسول ۾ ڇاڪاڻ ته اسان انهن جي پيداوار کي پروگرام ڪيو آهي toString()ڪلاس جي طريقي ۾ Cat. هتي اسان ان ڪلاس جو نالو پڙهون ٿا جنهن جو اعتراض اسان ڪنسول مان ٺاهينداسين. هلندڙ پروگرام ان ڪلاس جو نالو سکي ٿو جنهن جو اعتراض اهو ٺاهيندو. عڪس استعمال ڪرڻ جا مثال - 3اختصار جي خاطر، اسان مناسب استثنيٰ سنڀالڻ لاءِ ڪوڊ ڪڍي ڇڏيو آهي ته جيئن اهو مثال کان وڌيڪ جاءِ نه وٺي. هڪ حقيقي پروگرام ۾، يقينا، اهو يقيني طور تي حالتن کي سنڀالڻ جي قابل آهي جتي غلط نالا داخل ڪيا ويا آهن، وغيره. ڊفالٽ ڪنسٽرڪٽر بلڪل سادي شيءِ آهي، تنهنڪري ان کي استعمال ڪندي هڪ ڪلاس جو مثال ٺاهڻ، جيئن توهان ڏسي سگهو ٿا، ڏکيو نه آهي :) ۽ طريقو استعمال ڪندي، newInstance()اسان هن طبقي جو هڪ نئون اعتراض ٺاهيندا آهيون. اهو ٻيو معاملو آهي جيڪڏهن ڪلاس تعمير ڪندڙ Catپيٽرولر کي ان پٽ طور وٺي ٿو. اچو ته ڊفالٽ ڪنسٽرڪٽر کي ڪلاس مان ڪڍون ۽ ڪوشش ڪريون اسان جو ڪوڊ ٻيهر.

null
java.lang.InstantiationException: learn.javarush.Cat
  at java.lang.Class.newInstance(Class.java:427)
ڪجهه غلط ٿي ويو! اسان کي هڪ غلطي ملي آهي ڇو ته اسان ڊفالٽ ڪنسٽرڪٽر ذريعي اعتراض ٺاهڻ لاءِ هڪ طريقو سڏيو آهي. پر هاڻي اسان وٽ اهڙو ڊزائنر ناهي. هن جو مطلب اهو آهي ته جڏهن طريقو ڪم ڪري ٿو، newInstance()عکاس ميڪانيزم اسان جي پراڻي تعمير ڪندڙ کي ٻن پيٽرولن سان استعمال ڪندو:
public Cat(String name, int age) {
   this.name = name;
   this.age = age;
}
پر اسان پيرا ميٽرن سان ڪجهه به نه ڪيو، ڄڻ ته اسان انهن بابت مڪمل طور تي وساري ڇڏيو هو! عڪس استعمال ڪندي انهن کي تعمير ڪندڙ ڏانهن منتقل ڪرڻ لاء، توهان کي ان کي ٿوري ٽائيڪ ڪرڻو پوندو:
import learn.javarush.Cat;

import java.lang.reflect.InvocationTargetException;

public class Main {

   public static Cat createCat()  {

       Class clazz = null;
       Cat cat = null;

       try {
           clazz = Class.forName("learn.javarush.Cat");
           Class[] catClassParams = {String.class, int.class};
           cat = (Cat) clazz.getConstructor(catClassParams).newInstance("Barsik", 6);
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       } catch (InstantiationException e) {
           e.printStackTrace();
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       } catch (NoSuchMethodException e) {
           e.printStackTrace();
       } catch (InvocationTargetException e) {
           e.printStackTrace();
       }

       return cat;
   }

   public static void main(String[] args) {
       System.out.println(createCat());
   }
}
ڪنسول آئوٽ:

Cat{name='Barsik', age=6}
اچو ته هڪ ويجهي نظر رکون ته اسان جي پروگرام ۾ ڇا ٿي رهيو آهي. اسان شين جو هڪ صف ٺاهيو آهي Class.
Class[] catClassParams = {String.class, int.class};
اهي اسان جي تعمير ڪندڙ جي پيٽرولن سان ملن ٿا (اسان وٽ صرف پيٽرولر String۽ int). اسان انهن کي طريقي سان منتقل ڪيو clazz.getConstructor()۽ گهربل تعمير ڪندڙ تائين رسائي حاصل ڪريو. ان کان پوء، باقي رهي ٿو ته طريقي کي newInstance()ضروري پيٽرولن سان سڏين ۽ واضح طور تي اعتراض کي ڪلاس ۾ اڇلائڻ نه وساريو جيڪو اسان جي ضرورت آهي - Cat.
cat = (Cat) clazz.getConstructor(catClassParams).newInstance("Barsik", 6);
نتيجي طور، اسان جو اعتراض ڪاميابي سان پيدا ڪيو ويندو! ڪنسول آئوٽ:

Cat{name='Barsik', age=6}
اچو ته اڳتي وڌون :)

ڪنهن شئي جي فيلڊ جو قدر ڪيئن حاصل ڪجي ۽ سيٽ ڪجي نالي سان

تصور ڪريو ته توھان ھڪڙو ڪلاس استعمال ڪري رھيا آھيو جيڪو ٻئي پروگرامر پاران لکيل آھي. بهرحال، توهان کي ان کي تبديل ڪرڻ جو موقعو نه آهي. مثال طور، هڪ تيار ڪيل ڪلاس لائبريري هڪ JAR ۾ ڀريل. توھان پڙھي سگھوٿا ڪلاس ڪوڊ، پر توھان ان کي تبديل نٿا ڪري سگھو. پروگرامر جنهن هن لائبريريءَ ۾ ڪلاس ٺاهيو (اچو ته اهو اسان جو پراڻو طبقو هجي Cat) فائنل ڊيزائن کان اڳ ڪافي ننڊ نه ڪئي ۽ فيلڊ لاءِ گيٽرز ۽ سيٽرز ڪڍي ڇڏيا age. هاڻي هي طبقو توهان وٽ آيو آهي. اهو مڪمل طور تي توهان جي ضرورتن کي پورو ڪري ٿو، ڇو ته توهان کي صرف پروگرام ۾ شين جي ضرورت آهي Cat. پر توهان کي انهن جي ضرورت آهي ساڳئي فيلڊ سان age! اھو ھڪڙو مسئلو آھي: اسان فيلڊ تائين پھچي نٿا سگھون، ڇاڪاڻ⁠تہ اھو ھڪڙو موڊيفائر آھي private، ۽ حاصل ڪندڙ ۽ سيٽرز کي ھن طبقي جي ڊولپر پاران ھٽايو ويو آھي:/ خير، عکاسي ھن صورتحال ۾ پڻ اسان جي مدد ڪري سگھي ٿي! Catاسان وٽ ڪلاس ڪوڊ تائين پهچ آهي : اسان گهٽ ۾ گهٽ اهو معلوم ڪري سگهون ٿا ته ان جا ڪهڙا فيلڊ آهن ۽ انهن کي ڇا چئبو آهي. هن معلومات سان هٿياربند، اسان اسان جو مسئلو حل ڪريون ٿا:
import learn.javarush.Cat;

import java.lang.reflect.Field;

public class Main {

   public static Cat createCat()  {

       Class clazz = null;
       Cat cat = null;
       try {
           clazz = Class.forName("learn.javarush.Cat");
           cat = (Cat) clazz.newInstance();

           //с полем name нам повезло - для него в классе есть setter
           cat.setName("Barsik");

           Field age = clazz.getDeclaredField("age");

           age.setAccessible(true);

           age.set(cat, 6);

       } catch (IllegalAccessException e) {
           e.printStackTrace();
       } catch (InstantiationException e) {
           e.printStackTrace();
       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       } catch (NoSuchFieldException e) {
           e.printStackTrace();
       }

       return cat;
   }

   public static void main(String[] args) {
       System.out.println(createCat());
   }
}
جيئن ته تبصرو ۾ چيو ويو آهي، nameهر شيء سادو آهي فيلڊ سان: ڪلاس جي ڊولپرز ان لاء هڪ سيٽر مهيا ڪيو. توھان اڳ ۾ ئي ڄاڻو ٿا ته ڊفالٽ ٺاھيندڙن مان شيون ڪيئن ٺاھيو: ھن لاء ھڪڙو طريقو آھي newInstance(). پر ٻئي فيلڊ سان توهان کي ٽينڪر ڪرڻو پوندو. اچو ته سمجهون ته هتي ڇا ٿي رهيو آهي :)
Field age = clazz.getDeclaredField("age");
هتي اسان، اسان جي اعتراض کي استعمال ڪندي Class clazz، ageاستعمال ڪندي فيلڊ تائين رسائي ڪريو getDeclaredField(). اهو اسان کي هڪ اعتراض جي طور تي عمر جي ميدان کي حاصل ڪرڻ جي صلاحيت ڏئي ٿو Field age. پر اهو اڃا ڪافي نه آهي، ڇاڪاڻ ته privateفيلڊ کي صرف قدر مقرر نه ٿي ڪري سگھجي. هن کي ڪرڻ لاء، توهان کي طريقو استعمال ڪندي فيلڊ کي "دستياب" ڪرڻ جي ضرورت آهي setAccessible():
age.setAccessible(true);
اهي شعبا جن لاءِ اهو ڪيو ويو آهي قيمتون مقرر ڪري سگهجن ٿيون:
age.set(cat, 6);
جئين توهان ڏسي سگهو ٿا، اسان وٽ هڪ قسم جو سيٽر مٿي ڦيرايو ويو آهي: اسان فيلڊ کي Field ageان جي قيمت تفويض ڪريون ٿا، ۽ ان کي اهو اعتراض پڻ ڏئي ٿو ته هن فيلڊ کي تفويض ڪيو وڃي. اچو ته اسان جو طريقو هلون main()۽ ڏسو:

Cat{name='Barsik', age=6}
عظيم، اسان اهو سڀ ڪجهه ڪيو! :) اچو ته ڏسون ته اسان وٽ ٻيا ڪهڙا امڪان آهن...

ڪنهن شئي جي طريقي کي نالي سان ڪيئن سڏجي

اچو ته پوئين مثال کان صورتحال کي ٿورو تبديل ڪريون. اچو ته چوندا آهن ڪلاس ڊولپر Catفيلڊ سان غلطي ڪئي آهي - ٻئي موجود آهن، انهن لاء حاصل ڪندڙ ۽ سيٽرز آهن، سڀ ڪجهه ٺيڪ آهي. مسئلو مختلف آهي: هن هڪ خانگي طريقو ٺاهيو جنهن جي اسان کي ضرور ضرورت آهي:
private void sayMeow() {

   System.out.println("Meow!");
}
نتيجي طور، اسان Catاسان جي پروگرام ۾ شيون ٺاهي سگهنداسين، پر انهن جي طريقي کي سڏڻ جي قابل نه هوندا sayMeow(). ڇا اسان وٽ ٻليون هونديون جيڪي ميون نه ڪن؟ بلڪل عجيب :/ مان ان کي ڪيئن ٺيڪ ڪري سگهان ٿو؟ هڪ ڀيرو ٻيهر، Reflection API اچي ٿو بچاءُ لاءِ! اسان کي گهربل طريقي جو نالو ڄاڻو ٿا. باقي ٽيڪنڪ جو معاملو آهي:
import learn.javarush.Cat;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class Main {

   public static void invokeSayMeowMethod()  {

       Class clazz = null;
       Cat cat = null;
       try {

           cat = new Cat("Barsik", 6);

           clazz = Class.forName(Cat.class.getName());

           Method sayMeow = clazz.getDeclaredMethod("sayMeow");

           sayMeow.setAccessible(true);

           sayMeow.invoke(cat);

       } catch (ClassNotFoundException e) {
           e.printStackTrace();
       } catch (NoSuchMethodException e) {
           e.printStackTrace();
       } catch (IllegalAccessException e) {
           e.printStackTrace();
       } catch (InvocationTargetException e) {
           e.printStackTrace();
       }
   }

   public static void main(String[] args) {
       invokeSayMeowMethod();
   }
}
هتي اسان گهڻو ئي ساڳيو طريقي سان عمل ڪندا آهيون جيئن ڪنهن خانگي فيلڊ تائين رسائي جي صورتحال ۾. پهرين اسان کي اهو طريقو ملي ٿو جيڪو اسان کي گهربل آهي، جيڪو هڪ طبقي اعتراض ۾ شامل ڪيو ويو آهي Method:
Method sayMeow = clazz.getDeclaredMethod("sayMeow");
مدد سان، getDeclaredMethod()توھان ڪري سگھو ٿا ”پھچي“ پرائيويٽ طريقن سان. ان کان پوء اسان طريقي کي ڪال ڪرڻ جي قابل بڻايون ٿا:
sayMeow.setAccessible(true);
۽ نيٺ، اسان کي گهربل اعتراض تي طريقو سڏين ٿا:
sayMeow.invoke(cat);
هڪ طريقي کي ڪال ڪرڻ به ”ڪال ان ريورس“ وانگر نظر اچي ٿو: اسان هڪ نقطي استعمال ڪندي ڪنهن شئي کي گهربل طريقي ڏانهن اشارو ڪرڻ لاءِ استعمال ڪيو ويندو آهي ( cat.sayMeow())، ۽ جڏهن عڪاسي سان ڪم ڪري رهيا آهيون، اسان ان طريقي ڏانهن وڃون ٿا جنهن شئي کي سڏڻ جي ضرورت آهي. . اسان وٽ ڪنسول ۾ ڇا آهي؟

Meow!
سڀ ڪجھ ڪم ڪيو! :) هاڻي توهان ڏسو ٿا ته جاوا ۾ ريفريڪشن ميڪنزم اسان کي ڪهڙا وسيع امڪان ڏئي ٿو. مشڪل ۽ غير متوقع حالتن ۾ (جيئن ته مثالن ۾ بند ٿيل لائبريري مان ڪلاس سان)، اهو واقعي اسان جي مدد ڪري سگهي ٿو. بهرحال، ڪنهن به وڏي طاقت وانگر، اهو پڻ وڏي ذميواري جو مطلب آهي. عڪاسي جي نقصانن بابت لکيو ويو آهي خاص سيڪشن ۾ Oracle ويب سائيٽ تي. اتي ٽي مکيه نقصان آهن:
  1. پيداوار گھٽجي ٿي. طريقن کي استعمال ڪندي سڏيو ويندو آهي ريفريڪشن استعمال ڪندي انهن طريقن جي ڀيٽ ۾ گهٽ ڪارڪردگي آهي جن کي عام طور تي سڏيو ويندو آهي.

  2. اتي حفاظتي پابنديون آهن. ريفريڪشن ميڪانيزم توهان کي اجازت ڏئي ٿو ته رن ٽائم دوران پروگرام جي رويي کي تبديل ڪري. پر توهان جي ڪم جي ماحول ۾ هڪ حقيقي منصوبي تي پابنديون هونديون جيڪي توهان کي ائين ڪرڻ جي اجازت نه ڏيندا آهن.

  3. اندروني معلومات جي ظاهر ٿيڻ جو خطرو. اهو سمجهڻ ضروري آهي ته عڪاسي استعمال ڪندي سڌي طرح encapsulation جي اصول جي ڀڃڪڙي ڪري ٿي: اهو اسان کي نجي شعبن، طريقن، وغيره تائين رسائي جي اجازت ڏئي ٿو. مان سمجهان ٿو ته وضاحت ڪرڻ جي ڪا ضرورت ناهي ته او او پي جي اصولن جي سڌي ۽ مجموعي خلاف ورزي کي صرف انتهائي سخت حالتن ۾ استعمال ڪيو وڃي، جڏهن توهان جي ڪنٽرول کان ٻاهر سببن جي ڪري مسئلي کي حل ڪرڻ جا ٻيا طريقا نه آهن.

عڪاسي ميڪانيزم کي عقلمنديءَ سان استعمال ڪريو ۽ صرف انهن حالتن ۾ جتي ان کان بچي نٿو سگهجي، ۽ ان جي خامين کي نه وساريو. هي اسان جي ليڪچر کي ختم ڪري ٿو! اهو تمام وڏو ٿي ويو، پر اڄ توهان تمام گهڻو نيون شيون سکيو :)
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION