JavaRush /Java Blog /Random-TK /Java-da oýlanma - Ulanyş mysallary

Java-da oýlanma - Ulanyş mysallary

Toparda çap edildi
Gündelik durmuşda “pikirlenmek” düşünjesine duş gelen bolmagyňyz mümkin. Adatça bu söz özüni öwrenmek prosesine degişlidir. Programmirlemekde şuňa meňzeş many bar - bu bir programma baradaky maglumatlary barlamagyň, şeýle hem programmanyň ýerine ýetirilişiniň gurluşyny we özüni alyp barşyny üýtgetmek üçin mehanizmdir. Bu ýerde möhüm zat, kompil wagtynda däl-de, iş wagty ýerine ýetirilýär. Whyöne näme üçin iş wagty kody gözden geçirmeli? Siz eýýäm gördüňiz: / Oýlanma ulanmagyň mysallary - 1Oýlanmak pikiri bir sebäbe görä derrew düşnüksiz bolup biler: şu wagta çenli işleýän synplaryňyzy elmydama bilýärdiňiz. Mysal üçin, synp ýazyp bilersiňiz 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 +
           '}';
}

}
Bu hakda hemme zady bilýärsiň, haýsy meýdanlaryň we usullaryň bardygyny görýärsiň. AnimalElbetde , programma beýleki haýwanlara mätäç bolsa, amatlylyk üçin umumy synp bilen miras ulgamyny döredip bilersiňiz . Ozal hatda ene-atadan geçip boljak weterinariýa klinikasy synpyny hem döredipdik Animal, bu programma haýwanyň it ýa-da pişikdigine baglylykda bejergi alardy. Bu meseleler gaty ýönekeý bolmasa-da, programma sapak wagtynda zerur bolan ähli maglumatlary öwrenýär. Şonuň üçin main()haýsydyr bir obýekti Catweterinariýa kliniki synpynyň usullaryna geçireniňizde, programma munuň it däl-de, pişikdigini eýýäm bilýär. Indi başga bir mesele bilen ýüzbe-ýüz bolýandygymyzy göz öňüne getireliň. Biziň maksadymyz kod analizatoryny ýazmak. CodeAnalyzerMethodeke-täk usul bilen synp döretmeli - void analyzeClass(Object o). Bu usul:
  • obýektiň haýsy klasa geçendigini kesgitläň we konsolda synp adyny görkeziň;
  • bu synpyň ähli meýdanlarynyň atlaryny kesgitläň, şol sanda hususy bölümleri we konsolda görkeziň;
  • bu synpyň ähli usullarynyň, şol sanda hususy usullaryň atlaryny kesgitläň we konsolda görkeziň.
Munuň ýaly bir zat görüner:
public class CodeAnalyzer {

   public static void analyzeClass(Object o) {

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

}
Indi bu meseläniň we öň çözen beýleki meseleleriň arasyndaky tapawut görünýär. Bu ýagdaýda kynçylyk, ne seniň, ne-de programmanyň usula nämäniň beriljekdigini bilmeýändiginden ybaratdyr analyzeClass(). Bir programma ýazarsyňyz, beýleki programmistler ony ulanyp başlar, kim bu usula islendik zady geçirip biler - islendik adaty Java synpy ýa-da ýazan islendik synpy. Bu synpda islendik üýtgeýjiler we usullar bolup biler. Başgaça aýdylanda, bu ýagdaýda haýsy synplar bilen işlejekdigimizi bilemzok (we programmamyz). Şeýle-de bolsa, bu meseläni çözmeli. Ine, adaty Java kitaphanasy bize kömek edýär - Java Reflection API. Reflection API güýçli dil aýratynlygydyr. Resmi Oracle resminamalarynda bu mehanizmiň diňe edýän işlerine gaty gowy düşünýän tejribeli programmistler tarapyndan ulanylmagy maslahat berilýär. Näme üçin duýdansyz beýle duýduryş berilýändigimize tiz wagtdan düşünersiňiz :) Ine, Reflection API ulanyp boljak zatlaryň sanawy:
  1. Obýektiň synpyny tapyň / kesgitläň.
  2. Synp üýtgedijileri, meýdanlary, usullary, yzygiderliligi, konstruktorlary we superklasslary barada maglumat alyň.
  3. Geçirilen interfeýslere / interfeýslere haýsy usullara degişlidigini biliň.
  4. Programma ýerine ýetirilýänçä synpyň ady belli bolmadyk mahaly synpyň mysalyny dörediň.
  5. Obýekt meýdanynyň adyny alyň we belläň.
  6. Obýektiň usulyna at bilen jaň ediň.
Täsirli sanaw, şeýlemi? :) Üns beriň:Oýlanmak mehanizmi, kod analizatorymyza haýsy synp obýektine geçendigimize garamazdan, bularyň hemmesini “uçup bilýär”! Geliň, Reflection API mümkinçiliklerine mysallar bilen seredeliň.

Obýektiň synpyny nädip tapmaly / kesgitlemeli

Esasy zatlardan başlalyň. Java-yň şöhlelendiriş mehanizmine giriş nokady Class. Hawa, hakykatdanam gülkünç görünýär, ýöne şonuň üçin pikirlenmek şeýledir :) Bir synp ulanyp Class, ilki bilen usulymyza geçen islendik obýektiň synpyny kesgitleýäris. Muny synap göreliň:
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));
   }
}
Konsol çykyşy:

class learn.javarush.Cat
Iki zada üns beriň. Ilki bilen, bilkastlaýyn synpy Cataýratyn bukja salýarys, indi synpyň doly adyny yzyna gaýtaryp berýändigini learn.javarush;görüp bilersiňiz . getClass()Ikinjiden, üýtgeýjimize at dakdyk clazz. Biraz geň görünýär. Elbetde, oňa “synp” diýilmeli, ýöne “synp” Java dilinde ätiýaçlandyrylan söz we düzüji üýtgeýänleriň beýle atlandyrylmagyna ýol bermez. Ondan çykmaly boldum :) Gowy başlangyç däl! Mümkinçilikleriň sanawynda başga näme bar?

Synp üýtgedijileri, meýdanlary, usullary, yzygiderliligi, konstruktorlary we superklasslary barada nädip maglumat almaly

Bu eýýäm has gyzykly! Häzirki synpda yzygiderli we ene synpymyz ýok. Doly dolulygyna goşalyň. Iň ýönekeý ene-atalar synpyny döredeliň Animal:
package learn.javarush;
public class Animal {

   private String name;
   private int age;
}
Geliň, synpymyza Catmiras we hemişelik goşalyň:Animal
package learn.javarush;

public class Cat extends Animal {

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

   private String name;
   private int age;

   //...остальная часть класса
}
Indi doly toplumymyz bar! Oýlanmagyň mümkinçiliklerini synap göreliň :)
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));
   }
}
Konsolda alýan zatlarymyz:
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)]
Synp hakda gaty jikme-jik maglumat aldyk! Diňe köpçülige däl, şahsy böleklere-de degişlidir. Üns beriň: privateüýtgeýjiler sanawda hem görkezilýär. Aslynda, synpyň “derňewi” şu wagt doly hasap edilip bilner: indi usuly ulanyp, analyzeClass()mümkin bolan ähli zady öwreneris. Emma bularyň hemmesi pikirlenmek bilen işleýän wagtymyz bar mümkinçilikler däl. Simpleönekeý synlamak bilen çäklenmän, işjeň herekete geçeliň! :)

Programma ýerine ýetirilmänkä synpyň ady näbelli bolsa, synpyň mysalyny nädip döretmeli

Adaty konstruktordan başlalyň. Bu entek synpymyzda ýok Cat, geliň goşalyň:
public Cat() {

}
CatIne, kod şöhlelenme (usul) ulanyp obýekt döretmek üçin nähili görüner 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());
   }
}
Konsola giriň:

learn.javarush.Cat
Konsol çykyşy:

Cat{name='null', age=0}
Bu ýalňyşlyk däl: bahalar namewe agekonsolda görkezilýär, sebäbi olaryň çykyşlaryny toString()synp usulynda programmirledik Cat. Bu ýerde konsoldan obýekt döredjek synpymyzyň adyny okaýarys. Işleýän programma, obýektini döredjek synpyň adyny öwrenýär. Oýlanmagy ulanmagyň mysallary - 3Gysga wagtlyk bolmagy üçin, mysalyň özünden has köp ýer tutmazlygy üçin kadadan çykma koduny goýduk. Hakyky programmada, elbetde, nädogry atlaryň girizilen we ş.m. ýagdaýlaryny çözmeli. Deslapky konstruktor diýseň ýönekeý bir zat, şonuň üçin ony ulanmagyň synpyny görmek, görşüňiz ýaly kyn däl :) Usuly ulanyp, newInstance()bu synpyň täze obýektini döredýäris. CatSynp konstruktory parametrleri giriş hökmünde alsa başga mesele . Geliň, deslapky konstruktory synpdan aýyralyň we kodumyzy täzeden işletmäge synanyşalyň.

null
java.lang.InstantiationException: learn.javarush.Cat
  at java.lang.Class.newInstance(Class.java:427)
Bir zat ýalňyş boldy! Thealňyşlyk aldyk, sebäbi deslapky konstruktoryň üsti bilen obýekt döretmek usulyny çagyrdyk. Emma indi beýle dizaýner ýok. Bu, usul işlän mahaly, newInstance()şöhlelendiriş mehanizminiň köne konstruktorymyzy iki parametr bilen ulanjakdygyny aňladýar:
public Cat(String name, int age) {
   this.name = name;
   this.age = age;
}
Emma parametrler bilen hiç zat etmedik, olar hakda düýbünden ýatdan çykaran ýaly! Olary şöhlelendiriş arkaly konstruktoryň ýanyna geçirmek üçin ony birneme gowulaşdyrmaly bolarsyňyz:
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());
   }
}
Konsol çykyşy:

Cat{name='Barsik', age=6}
Geliň, programmamyzda bolup geçýän zatlara has içgin seredeliň. Obýektleriň toplumyny döretdik Class.
Class[] catClassParams = {String.class, int.class};
Olar konstruktorymyzyň parametrlerine laýyk gelýär (bizde diňe parametrler bar String) int. Olary usula geçirýäris clazz.getConstructor()we zerur konstruktora girýäris. Ondan soň, newInstance()zerur parametrler bilen usuly çagyrmak we obýekti zerur klasa aç-açan taşlamagy ýatdan çykarmaň Cat.
cat = (Cat) clazz.getConstructor(catClassParams).newInstance("Barsik", 6);
Netijede, obýektimiz üstünlikli dörediler! Konsol çykyşy:

Cat{name='Barsik', age=6}
Geliň dowam edeliň :)

Obýekt meýdanynyň adyny nädip almaly we nädip kesgitlemeli

Başga bir programmist tarapyndan ýazylan synpy ulanýandygyňyzy göz öňüne getiriň. Şeýle-de bolsa, ony redaktirlemäge mümkinçilik ýok. Mysal üçin, JAR-da gaplanan taýýar synp kitaphanasy. Synp koduny okap bilersiňiz, ýöne üýtgedip bilmersiňiz. Bu kitaphanada synp döreden programmist (köne synpymyz bolsun Cat) soňky dizaýndan öň ýeterlik uky alyp bilmedi we meýdança girýänleri we sazlaýjylary aýyrdy age. Indi bu synp size geldi. Bu siziň islegleriňizi doly kanagatlandyrýar, sebäbi programmada diňe zatlar gerek Cat. Themöne olara şol bir meýdan gerek age! Bu bir mesele: meýdana baryp bilmeris, sebäbi üýtgediji bar privatewe girişleri we sazlaýjylary bu synpy dörediji tarapyndan aýyrdy: / ​​Garaz, bu ýagdaýda pikirlenmek hem bize kömek edip biler! Synp kody bar Cat: iň bolmanda haýsy meýdanlaryň bardygyny we näme diýilýändigini bilip bileris. Bu maglumatlar bilen ýaraglanan meselämizi çözýäris:
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());
   }
}
Teswirde aýdylyşy ýaly, namehemme zat meýdan bilen ýönekeý: synpy döredijiler munuň üçin kesgitleýji üpjün etdiler. Şeýle hem, deslapky konstruktorlardan obýektleri nädip döretmelidigini eýýäm bilýärsiňiz: munuň üçin bir usul bar newInstance(). Secondöne ikinji meýdan bilen pikirlenmeli bolarsyňyz. Geliň, bu ýerde näme bolýandygyny anyklalyň :)
Field age = clazz.getDeclaredField("age");
Bu ýerde, obýektimizi ulanyp Class clazz, meýdana agegirýäris getDeclaredField(). Bize ýaş meýdanyny obýekt hökmünde almaga mümkinçilik berýär Field age. Emma bu entek ýeterlik däl, sebäbi privatemeýdanlara diňe bahalar bellenip bilinmez. Munuň üçin usuly ulanyp, meýdançany “elýeterli” etmeli setAccessible():
age.setAccessible(true);
Munuň üçin ýerine ýetirilen meýdanlara bahalar berlip bilner:
age.set(cat, 6);
Görşüňiz ýaly, bizde bir hili sazlaýjy bar: meýdanyň Field agebahasyny belläris, şeýle hem bu meýdanyň berilmeli obýektini geçireris. Usulymyzy işledeliň main()we göreliň:

Cat{name='Barsik', age=6}
Gowy, hemmesini etdik! :) Geliň, başga mümkinçiliklerimiziň bardygyny göreliň ...

Obýektiň usulyny nädip at bilen atlandyrmaly

Öňki mysaldan ýagdaýy azajyk üýtgedeliň. CatSynp döredijisi meýdanlarda ýalňyşlyk goýberdi diýeliň - ikisi hem bar, olar üçin giriş we sazlaýjylar bar, hemme zat gowy. Mesele başgaçarak: hökmany suratda bize zerur bir usuly etdi:
private void sayMeow() {

   System.out.println("Meow!");
}
Netijede, programmamyzda obýektler dörederis Cat, ýöne olaryň usulyna jaň edip bilmeris sayMeow(). Meýdan etmeýän pişiklerimiz barmy? Gaty geň: / Muny nädip düzedip bilerin? Reflectionene bir gezek Reflection API kömege gelýär! Gerekli usulyň adyny bilýäris. Galanlary tehnika meselesi:
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();
   }
}
Bu ýerde, hususy meýdana girmek bilen ýagdaýdaky ýaly hereket edýäris. Ilki bilen synp obýektinde jemlenen zerur usuly alýarys Method:
Method sayMeow = clazz.getDeclaredMethod("sayMeow");
Kömek bilen, getDeclaredMethod()hususy usullara “ýetip” bilersiňiz. Ondan soň usuly çagyryp bileris:
sayMeow.setAccessible(true);
Netijede, usuly islenýän obýektde atlandyrýarys:
sayMeow.invoke(cat);
Usula jaň etmek hem “tersine jaň” ýaly görünýär: nokat () ulanyp, bir obýekti zerur usula gönükdirmäge öwrenişdik cat.sayMeow()we şöhlelenme bilen işlänimizde, çagyrylmaly obýektiň usulyna geçýäris. . Konsolda näme bar?

Meow!
Hemme zat netije berdi! :) Indi Java-da şöhlelendiriş mehanizminiň bize nähili giň mümkinçilikleri berýändigini görýärsiňiz. Kyn we garaşylmadyk ýagdaýlarda (ýapyk kitaphananyň synpyndaky mysallardaky ýaly), bu hakykatdanam bize köp kömek edip biler. Şeýle-de bolsa, islendik beýik güýç ýaly, uly jogapkärçiligi hem göz öňünde tutýar. Oýlanmagyň kemçilikleri Oracle web sahypasyndaky ýörite bölümde ýazylýar . Üç esasy kemçilik bar:
  1. Önümçilik peselýär. Oýlanmak arkaly atlandyrylýan usullar adaty diýilýän usullardan has pes öndürijilige eýe.

  2. Howpsuzlyk çäklendirmeleri bar. Oýlanmak mehanizmi, iş wagty programmanyň özüni alyp barşyny üýtgetmäge mümkinçilik berýär. Emma hakyky taslama boýunça iş gurşawyňyzda, muny etmäge rugsat bermeýän çäklendirmeler bolup biler.

  3. Içerki maglumatlaryň aýan edilmek töwekgelçiligi. Oýlanmagy ulanmak encapsulýasiýa prinsipini gönüden-göni bozýar diýip düşünmek möhümdir: bu şahsy meýdanlara, usullara we ş.m. girmäge mümkinçilik berýär. OOP ýörelgeleriniň gönüden-göni we gödek bozulmagynyň diňe iň aşa agyr ýagdaýlarda ulanylmalydygyny düşündirmegiň zerurlygy ýok diýip pikir edýärin.

Oýlanmak mehanizmini paýhasly we diňe öňüni alyp bolmajak ýagdaýlarda ulanyň we kemçiliklerini ýatdan çykarmaň. Bu leksiýamyzy tamamlaýar! Örän uly boldy, ýöne bu gün köp täze zatlar öwrendiň :)
Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION