CodeGym /جاوا بلاگ /Random-SD /عکاسي جا مثال
John Squirrels
سطح
San Francisco

عکاسي جا مثال

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

package learn.codegym;

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، ۽ پروگرام جانور کي مناسب طور تي علاج ڪيو آھي ان جي بنياد تي ته اھو ڪتو آھي يا ٻلي. جيتوڻيڪ اهي آسان ترين ڪم نه آهن، پروگرام مرتب وقت تي ڪلاس بابت تمام ضروري معلومات سکڻ جي قابل آهي. ان جي مطابق، جڏهن توهان هڪ Catاعتراض کي پاس ڪيو ويٽرنري ڪلينڪ ڪلاس جي طريقن جي main()طريقن ۾، پروگرام اڳ ۾ ئي ڄاڻي ٿو ته اهو هڪ ٻلي آهي، نه ڪتو. هاڻي اچو ته تصور ڪريون ته اسان هڪ مختلف ڪم کي منهن ڏئي رهيا آهيون. اسان جو مقصد ڪوڊ اينالائيزر لکڻ آهي. CodeAnalyzerاسان کي ھڪڙي ھڪڙي طريقي سان ھڪڙي ڪلاس ٺاهڻ جي ضرورت آھي : void analyzeObject(Object o). اهو طريقو گهرجي:
  • ان کي منظور ٿيل اعتراض جو ڪلاس مقرر ڪريو ۽ ڪنسول تي ڪلاس جو نالو ڏيکاريو؛
  • منظور ٿيل ڪلاس جي سڀني شعبن جا نالا مقرر ڪريو، جن ۾ خانگي شامل آهن، ۽ انهن کي ڪنسول تي ڏيکاريو؛
  • منظور ٿيل ڪلاس جي سڀني طريقن جا نالا مقرر ڪريو، جن ۾ خانگي به شامل آھن، ۽ انھن کي ڪنسول تي ڏيکاريو.
اهو ڪجهه هن طرح نظر ايندو:

public class CodeAnalyzer {

   public static void analyzeClass(Object o) {
      
       // Print the name of the class of object o
       // Print the names of all variables of this class
       // Print the names of all methods of this class
   }
  
}
هاڻي اسان واضح طور تي ڏسي سگهون ٿا ته هي ڪم ٻين ڪمن کان مختلف آهي جيڪي توهان اڳ ۾ حل ڪيا آهن. اسان جي موجوده مقصد سان، ڏکيائي ان حقيقت ۾ آهي ته نه اسان کي ۽ نه ئي پروگرام کي خبر آهي ته ڪهڙي طريقي سان گذري ويندي analyzeClass(). جيڪڏهن توهان اهڙو پروگرام لکندا آهيو، ٻيا پروگرامر ان کي استعمال ڪرڻ شروع ڪندا، ۽ اهي شايد هن طريقي سان ڪجهه به پاس ڪري سگھن ٿا - ڪنهن به معياري جاوا ڪلاس يا ڪنهن ٻئي طبقي جو اهي لکندا آهن. پاس ٿيل ڪلاس ۾ ڪي به تعداد ۽ طريقا ٿي سگھن ٿا. ٻين لفظن ۾، اسان کي (۽ اسان جو پروگرام) ڪا به خبر ناهي ته اسان ڪهڙن طبقن سان ڪم ڪنداسين. پر اڃا تائين، اسان کي هن ڪم کي مڪمل ڪرڻ جي ضرورت آهي. ۽ اهو آهي جتي معياري جاوا ريفليشن API اسان جي مدد لاءِ اچي ٿو. Reflection API ٻوليءَ جو هڪ طاقتور اوزار آهي. Oracle جي سرڪاري دستاويز سفارش ڪري ٿو ته هي ميکانيزم صرف تجربيڪار پروگرامرن پاران استعمال ڪيو وڃي جيڪي ڄاڻن ٿا ته اهي ڇا ڪري رهيا آهن. توھان جلد سمجھندا سين ڇو ته اسان ھن قسم جي ڊيڄاريندڙ اڳ ۾ ئي ڏئي رھيا آھيون :) ھتي انھن شين جي ھڪڙي فهرست آھي جيڪي توھان Reflection API سان ڪري سگھو ٿا:
  1. ڪنهن شئي جي درجي کي سڃاڻو/ متعين ڪريو.
  2. ڪلاس ميڊيفائرز، فيلڊز، طريقا، مستقل، تعمير ڪندڙ، ۽ سپر ڪلاس بابت ڄاڻ حاصل ڪريو.
  3. معلوم ڪريو ته ڪھڙا طريقا لاڳو ٿيل انٽرفيس سان تعلق رکن ٿا.
  4. ھڪڙي ڪلاس جو ھڪڙو مثال ٺاھيو جنھن جي ڪلاس جو نالو معلوم نه آھي جيستائين پروگرام تي عمل نه ڪيو وڃي.
  5. حاصل ڪريو ۽ نالي سان ھڪڙي مثال جي فيلڊ جي قيمت مقرر ڪريو.
  6. نالي سان هڪ مثالي طريقو ڪال ڪريو.
متاثر ڪندڙ فهرست، ها؟ :) نوٽ:ريفريڪشن ميڪنزم اهو سڀ ڪجهه ڪري سگهي ٿو ”اُڏام تي“، قطع نظر ڪنهن به شئي جي قسم جي اسان پنهنجي ڪوڊ اينالائيزر ڏانهن منتقل ڪريون ٿا! اچو ته Reflection API جي صلاحيتن کي ڳوليون ڪجھ مثالن کي ڏسڻ سان.

ڪنهن شئي جي درجي کي ڪيئن سڃاڻڻ/ طئي ڪرڻ

اچو ته بنيادي ڳالهين سان شروع ڪريون. جاوا ريفريڪشن انجڻ ۾ داخلا پوائنٽ Classڪلاس آھي. ها، اهو واقعي مضحکہ خیز ڏسڻ ۾ اچي ٿو، پر اهو اهو آهي جيڪو عڪس آهي :) Classڪلاس استعمال ڪندي، اسان پهريون ڀيرو طئي ڪندا آهيون ڪنهن به شئي جو ڪلاس اسان جي طريقي سان گذري ويو. اچو ته اهو ڪرڻ جي ڪوشش ڪريون:

import learn.codegym.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("Fluffy", 6));
   }
}
ڪنسول آئوٽ:

class learn.codegym.Cat
ٻن ڳالهين تي ڌيان ڏيو. پهرين، اسان عمدي طور Catڪلاس کي الڳ learn.codegymپيڪيج ۾ رکون ٿا. ھاڻي توھان ڏسي سگھو ٿا ته getClass()طريقو ڪلاس جو پورو نالو ڏئي ٿو. ٻيو، اسان نالو رکيو اسان جي متغير clazz. اهو ٿورڙو عجيب لڳندو آهي. ان کي ”طبقو“ سڏڻ جو مطلب ٿيندو، پر جاوا ۾ ”ڪلاس“ هڪ مخصوص لفظ آهي. مرتب ڪندڙ متغيرن کي ان کي سڏڻ جي اجازت نه ڏيندو. اسان کي انهي جي چوڌاري حاصل ڪرڻو پيو :) شروعات لاءِ خراب ناهي! اسان وٽ ان قابليت جي فهرست تي ٻيو ڇا آهي؟

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

هاڻي شيون وڌيڪ دلچسپ ٿي رهيون آهن! موجوده ڪلاس ۾، اسان وٽ ڪوبه مستقل يا والدين ڪلاس ناهي. اچو ته انهن کي شامل ڪريون مڪمل تصوير ٺاهڻ لاءِ. آسان ترين والدين ڪلاس ٺاهيو Animal:

package learn.codegym;
public class Animal {

   private String name;
   private int age;
}
Cat۽ اسان پنھنجي طبقي کي وارث بڻائينداسين Animal۽ ھڪڙو مسلسل شامل ڪنداسين:

package learn.codegym;

public class Cat extends Animal {

   private static final String ANIMAL_FAMILY = "Feline family";

   private String name;
   private int age;

   // ...the rest of the class
}
هاڻي اسان وٽ مڪمل تصوير آهي! اچو ته ڏسو ته ڪهڙو عڪاسي ڪرڻ جي قابل آهي :)

import learn.codegym.Cat;

import java.util.Arrays;

public class CodeAnalyzer {

   public static void analyzeClass(Object o) {
       Class clazz = o.getClass();
       System.out.println("Class name: " + clazz);
       System.out.println("Class fields: " + Arrays.toString(clazz.getDeclaredFields()));
       System.out.println("Parent class: " + clazz.getSuperclass());
       System.out.println("Class methods: " + Arrays.toString(clazz.getDeclaredMethods()));
       System.out.println("Class constructors: " + Arrays.toString(clazz.getConstructors()));
   }

   public static void main(String[] args) {

       analyzeClass(new Cat("Fluffy", 6));
   }
}
هتي اهو آهي جيڪو اسان ڪنسول تي ڏسون ٿا:
Class name:  class learn.codegym.Cat
Class fields: [private static final java.lang.String learn.codegym.Cat.ANIMAL_FAMILY, private java.lang.String learn.codegym.Cat.name, private int learn.codegym.Cat.age]
Parent class: class learn.codegym.Animal
Class methods: [public java.lang.String learn.codegym.Cat.getName(), public void learn.codegym.Cat.setName(java.lang.String), public void learn.codegym.Cat.sayMeow(), public void learn.codegym.Cat.setAge(int), public void learn.codegym.Cat.jump(), public int learn.codegym.Cat.getAge()]
Class constructors: [public learn.codegym.Cat(java.lang.String, int)]
ڏسو ته سڀني تفصيلي ڪلاس جي معلومات جيڪا اسان حاصل ڪرڻ جي قابل هئا! ۽ نه رڳو عوامي معلومات، پر نجي معلومات پڻ! نوٽ: privatevariables پڻ لسٽ ۾ ڏيکاريل آھن. اسان جي طبقي جو "تجزيو" لازمي طور تي مڪمل طور تي سمجهي سگهجي ٿو: اسان اهو analyzeObject()طريقو استعمال ڪري رهيا آهيون ته اسان هر شي کي سکڻ لاء. پر اهو سڀ ڪجهه ناهي جيڪو اسان عڪاسي سان ڪري سگهون ٿا. اسان صرف سادي مشاهدي تائين محدود نه آهيون - اسان عمل ڪرڻ لاءِ اڳتي وڌنداسين! :)

هڪ ڪلاس جو هڪ مثال ڪيئن ٺاهيو جنهن جي ڪلاس جو نالو معلوم نه هجي جيستائين پروگرام تي عمل نه ڪيو وڃي.

اچو ته ڊفالٽ ڪنسٽرڪٽر سان شروع ڪريون. اسان جي Catڪلاس ۾ اڃا تائين ھڪڙو نه آھي، تنھنڪري اچو ته ان کي شامل ڪريون:

public Cat() {
  
}
هتي آهي ڪوڊ ٺاهڻ لاءِ Catاعتراض استعمال ڪندي اعتراض ( createCat()طريقي):

import learn.codegym.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.codegym.Cat
ڪنسول آئوٽ:

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

null
java.lang.InstantiationException: learn.codegym.Cat 
at java.lang.Class.newInstance(Class.java:427)
ڪجهه غلط ٿي ويو! اسان کي هڪ غلطي ملي آهي ڇو ته اسان ڊفالٽ تعمير ڪندڙ استعمال ڪندي هڪ اعتراض ٺاهڻ لاء هڪ طريقو سڏيو آهي. پر هاڻي اسان وٽ اهڙو ڪو تعمير ڪندڙ ناهي. تنهن ڪري جڏهن newInstance()طريقو هلندو آهي، عکاسي ميڪانيزم اسان جي پراڻي تعمير ڪندڙ کي ٻن پيٽرولن سان استعمال ڪري ٿو:

public Cat(String name, int age) {
   this.name = name;
   this.age = age;
}
پر اسان پيرا ميٽرن سان ڪجهه به نه ڪيو، ڄڻ ته اسان انهن بابت مڪمل طور تي وساري ڇڏيو هو! تعمير ڪندڙ کي دليلن کي منتقل ڪرڻ لاء عڪاسي استعمال ڪندي ٿوري "تخليق" جي ضرورت آهي:

import learn.codegym.Cat;

import java.lang.reflect.InvocationTargetException;

public class Main {

   public static Cat createCat()  {

       Class clazz = null;
       Cat cat = null;

       try {
           clazz = Class.forName("learn.codegym.Cat");
           Class[] catClassParams = {String.class, int.class};
           cat = (Cat) clazz.getConstructor(catClassParams).newInstance("Fluffy", 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='Fluffy', age=6}
اچو ته هڪ ويجهي نظر رکون ته اسان جي پروگرام ۾ ڇا ٿي رهيو آهي. اسان Classشين جو هڪ صف ٺاهيو.

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

cat = (Cat) clazz.getConstructor(catClassParams).newInstance("Fluffy", 6);
هاڻي اسان جو اعتراض ڪاميابي سان پيدا ٿيو آهي! ڪنسول آئوٽ:

Cat{name='Fluffy', age=6}
ساڄي طرف هلڻو آهي :)

هڪ مثال جي فيلڊ جي قيمت ڪيئن حاصل ڪجي ۽ سيٽ ڪريو نالي سان.

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

import learn.codegym.Cat;

import java.lang.reflect.Field;

public class Main {

   public static Cat createCat()  {

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

           // We got lucky with the name field, since it has a setter
           cat.setName("Fluffy");

           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اعتراض ۾ هڪ قسم جو اندر-آئوٽ سيٽر آهي جنهن ۾ اسان هڪ int قدر ۽ اعتراض جنهن جي فيلڊ کي مقرر ڪيو وڃي ٿو. اسان پنهنجو main()طريقو هلون ٿا ۽ ڏسو:

Cat{name='Fluffy', age=6}
تمام سٺو! اسان ڪيو! :) اچو ته ڏسون ته اسان ٻيو ڇا ڪري سگهون ٿا ...

هڪ مثالي طريقي کي نالي سان ڪيئن سڏجي.

اچو ته پوئين مثال ۾ صورتحال کي ٿورو تبديل ڪريون. اچو ته چوندا آهن ته Catڪلاس ڊولپر حاصل ڪندڙن ۽ سيٽرن سان غلطي نه ڪئي. ان سلسلي ۾ سڀ ڪجهه ٺيڪ آهي. ھاڻي مسئلو مختلف آھي: ھڪڙو طريقو آھي جنھن جي اسان کي ضرور ضرورت آھي، پر ڊولپر ان کي خانگي بڻايو:

private void sayMeow() {

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

import learn.codegym.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("Fluffy", 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. اندروني معلومات جي نمائش جو خطرو. اهو سمجهڻ ضروري آهي ته عڪاسي انڪپسوليشن جي اصول جي سڌي خلاف ورزي آهي: اهو اسان کي نجي شعبن، طريقن، وغيره تائين رسائي ڏئي ٿو. مان نه ٿو سمجهان ته مون کي اهو ذڪر ڪرڻ جي ضرورت آهي ته او او پي جي اصولن جي سڌي ۽ واضح خلاف ورزي کي استعمال ڪيو وڃي. صرف انتهائي سخت ڪيسن ۾، جڏهن توهان جي ڪنٽرول کان ٻاهر سببن جي ڪري مسئلو حل ڪرڻ جا ٻيا طريقا نه آهن.

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