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 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
modifier, மற்றும் getter மற்றும் setter ஆகியவை தூக்கத்தை இழந்த டெவலப்பரால் நீக்கப்பட்டன வகுப்பிற்கான குறியீட்டிற்கான அணுகல் எங்களிடம் உள்ளது 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