कदाचित तुम्हाला सामान्य जीवनात "प्रतिबिंब" ही संकल्पना आली असेल. हा शब्द सहसा स्वतःचा अभ्यास करण्याच्या प्रक्रियेस सूचित करतो. प्रोग्रामिंगमध्ये, त्याचा समान अर्थ आहे - प्रोग्राम चालू असताना, प्रोग्रामबद्दल डेटाचे विश्लेषण करण्यासाठी आणि प्रोग्रामची रचना आणि वर्तन बदलण्यासाठी ही एक यंत्रणा आहे. येथे महत्त्वाचे आहे की आपण हे रनटाइमवर करत आहोत, संकलित वेळी नाही. पण रनटाइमच्या वेळी कोडचे परीक्षण का? शेवटी, आपण कोड आधीच वाचू शकता :/ प्रतिबिंबाची कल्पना त्वरित स्पष्ट न होण्याचे एक कारण आहे: या क्षणापर्यंत, आपण कोणत्या वर्गात काम करत आहात हे आपल्याला नेहमीच माहित होते. उदाहरणार्थ, तुम्ही
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()
पद्धत तुम्ही असा प्रोग्राम लिहिल्यास, इतर प्रोग्रामर ते वापरण्यास सुरुवात करतील, आणि ते या पद्धतीत काहीही पास करू शकतील — कोणताही मानक Java वर्ग किंवा इतर कोणताही वर्ग ते लिहितात. उत्तीर्ण वर्गात कितीही व्हेरिएबल्स आणि पद्धती असू शकतात. दुसऱ्या शब्दांत, आम्हाला (आणि आमच्या कार्यक्रमाला) आम्ही कोणत्या वर्गात काम करणार आहोत याची कल्पना नाही. परंतु तरीही, आपल्याला हे कार्य पूर्ण करणे आवश्यक आहे. आणि इथेच मानक Java Reflection API आमच्या मदतीला येते. रिफ्लेक्शन API हे भाषेचे शक्तिशाली साधन आहे. ओरॅकलचे अधिकृत दस्तऐवजीकरण शिफारस करते की ही यंत्रणा केवळ अनुभवी प्रोग्रामरद्वारे वापरली जावी ज्यांना ते काय करत आहेत हे माहित आहे. आम्ही अशा प्रकारची चेतावणी आगाऊ का देत आहोत हे तुम्हाला लवकरच समजेल :) रिफ्लेक्शन 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)]
आम्ही मिळवू शकलो ती सर्व तपशीलवार वर्ग माहिती पहा! आणि केवळ सार्वजनिक माहितीच नाही तर खाजगी माहिती देखील! टीप: private
व्हेरिएबल्स देखील सूचीमध्ये प्रदर्शित केले जातात. वर्गाचे आमचे "विश्लेषण" मूलत: पूर्ण मानले जाऊ शकते: आम्ही 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
. येथे आपण एका वर्गाचे नाव वाचतो ज्याचे ऑब्जेक्ट आपण कन्सोलमधून तयार करू. प्रोग्राम ज्या वर्गाचे ऑब्जेक्ट तयार करायचे आहे त्याचे नाव ओळखतो. संक्षिप्ततेसाठी, आम्ही योग्य अपवाद हाताळणी कोड वगळला, जो उदाहरणापेक्षा जास्त जागा घेईल. वास्तविक प्रोग्राममध्ये, अर्थातच, तुम्ही चुकीची प्रविष्ट केलेली नावे इत्यादींचा समावेश असलेल्या परिस्थिती हाताळल्या पाहिजेत. डीफॉल्ट कन्स्ट्रक्टर अगदी सोपे आहे, म्हणून तुम्ही पाहू शकता, वर्गाचा एक उदाहरण तयार करण्यासाठी त्याचा वापर करणे सोपे आहे :) पद्धत 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
ऑब्जेक्टमध्ये एक प्रकारचा इनसाईड-आउट सेटर आहे ज्याला आपण इंट व्हॅल्यू पास करतो आणि ज्या ऑब्जेक्टचे फील्ड नियुक्त करायचे आहे. आम्ही आमची पद्धत चालवतो main()
आणि पाहतो:
Cat{name='Fluffy', age=6}
उत्कृष्ट! आम्ही ते केले! :) बघू अजून काय करता येईल...
उदाहरण पद्धतीला नावाने कसे कॉल करावे.
मागील उदाहरणातील परिस्थिती थोडी बदलूया. समजा कीCat
क्लास डेव्हलपरने गेटर्स आणि सेटर्ससह चूक केली नाही. त्या संदर्भात सर्व काही ठीक आहे. आता समस्या वेगळी आहे: आम्हाला निश्चितपणे आवश्यक असलेली एक पद्धत आहे, परंतु विकसकाने ती खाजगी केली आहे:
private void sayMeow() {
System.out.println("Meow!");
}
याचा अर्थ असा की जर आपण आपल्या प्रोग्रॅममध्ये ऑब्जेक्ट्स तयार केले , तर आपण त्यावर पद्धत Cat
कॉल करू शकणार नाही . sayMeow()
आमच्याकडे मांजरी असतील जी म्याऊ करत नाहीत? हे विचित्र आहे :/ आम्ही याचे निराकरण कसे करू? पुन्हा एकदा, रिफ्लेक्शन 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!
सर्व काही काम केले! :) आता तुम्ही जावाच्या रिफ्लेक्शन मेकॅनिझमने दिलेल्या अफाट शक्यता पाहू शकता. कठीण आणि अनपेक्षित परिस्थितीत (जसे की बंद लायब्ररीतील वर्गातील आमची उदाहरणे), ते खरोखरच आम्हाला खूप मदत करू शकते. परंतु, कोणत्याही महान शक्तीप्रमाणे, ती मोठी जबाबदारी आणते. परावर्तनाचे तोटे ओरॅकल वेबसाइटवरील एका विशेष विभागात वर्णन केले आहेत. तीन मुख्य तोटे आहेत:
-
कामगिरी वाईट आहे. रिफ्लेक्शन वापरून कॉल केलेल्या पद्धतींची कामगिरी सामान्य पद्धतीने कॉल केलेल्या पद्धतींपेक्षा वाईट असते.
-
सुरक्षा निर्बंध आहेत. रिफ्लेक्शन मेकॅनिझम आपल्याला रनटाइमच्या वेळी प्रोग्रामचे वर्तन बदलू देते. परंतु तुमच्या कामाच्या ठिकाणी, एखाद्या वास्तविक प्रकल्पावर काम करताना, तुम्हाला मर्यादांचा सामना करावा लागू शकतो ज्या यास परवानगी देत नाहीत.
-
अंतर्गत माहिती उघड होण्याचा धोका. प्रतिबिंब हे एन्कॅप्सुलेशनच्या तत्त्वाचे थेट उल्लंघन आहे हे समजून घेणे महत्त्वाचे आहे: ते आम्हाला खाजगी फील्ड, पद्धती इत्यादींमध्ये प्रवेश करू देते. मला नाही वाटत की OOP च्या तत्त्वांचे थेट आणि स्पष्ट उल्लंघन केले पाहिजे. केवळ अत्यंत अत्यंत प्रकरणांमध्ये, जेव्हा तुमच्या नियंत्रणाबाहेरील कारणांमुळे समस्या सोडवण्याचे इतर कोणतेही मार्ग नसतात.
GO TO FULL VERSION