Kas yra apmąstymai ir kodėl tai naudinga?

Kas yra apmąstymai ir kodėl tai naudinga?

Mane ypač domina „Java“, bet manau, kad principai yra vienodi visomis kalbomis.

1812 m
01 сент. 01 Lehane rinkinys 2008-09-01 11:39 '08 at 11:39 2008-09-01 11:39
ответ 21 atsakymas

Vardų atspindys naudojamas apibūdinti kodą, kuris gali patikrinti kitą kodą toje pačioje sistemoje (arba pačioje sistemoje).

Pavyzdžiui, tarkime, kad „Java“ yra nežinomo tipo objektas ir norite jį pavadinti „doSomething“ metodu, jei jis yra. Statiška „Java“ spausdinimo sistema nėra sukurta tam, kad palaikytų tai, jei objektas neatitinka žinomos sąsajos, bet naudojant atspindį, jūsų kodas gali pažvelgti į objektą ir sužinoti, ar jis turi „doSomething“ metodą, tada paskambinkite, jei jūs nori

Taigi, norėdami suteikti jums šio kodo kodą „Java“ (tarkime, kad nagrinėjamas objektas yra foo):

 Method method = foo.getClass().getMethod("doSomething", null); method.invoke(foo, null); 

Vienas iš dažniausių „Java“ pavyzdžių yra anotacijų naudojimas. Pavyzdžiui, „JUnit 4“ naudos atspindį, kad peržiūrėtų jūsų klasių metodus, pažymėtus @Test anotacija, ir paskambinkite jiems, kai atliekamas vieneto bandymas.

Yra keletas gerų apmąstymų pavyzdžių, kurie gali padėti jums pradėti nuo http://docs.oracle.com/javase/tutorial/reflect/index.html.

Ir galiausiai, taip, sąvokos yra gana panašios į kitas statinio tipo kalbas, kurios palaiko atspindį (pvz., C #). Dinamiškai įvestomis kalbomis pirmiau aprašytas naudojimo atvejis yra mažiau reikalingas (kadangi kompiliatorius leidžia skambinti bet kuriuo metodu bet kuriame objekte, jei jis neveikia vykdymo metu, jei jis neegzistuoja), tačiau antrasis atvejų, kai ieškoma būdų, kurie pažymėti arba veikia tam tikra prasme, atvejis yra dažnas.

Atnaujinti iš komentaro:

Galimybė patikrinti kodą sistemoje ir matyti objektų tipus nėra atspindys, o įsivaizdavimas. Atspindėjimas - tai sugebėjimas keisti važiavimo laiką, naudojant savitarpio stebėjimą. Čia būtina atskirti, nes kai kurios kalbos palaiko savianalizę, bet nepalaiko refleksijos. Vienas iš tokių pavyzdžių yra C ++.

1500
01 сент. Atsakymą pateikė Matt Sheppard 01 Sep. 2008-09-01 11:44 '08 at 11:44 2008-09-01 11:44

Refleksija yra kalbos gebėjimas patikrinti ir dinamiškai remtis klasėmis, metodais, atributais ir tt vykdymo metu.

Pavyzdžiui, visi „Java“ objektai turi „ getClass() metodą, leidžiantį nustatyti objekto klasę, net jei nežinote kompiliavimo metu (pvz., Jei jį paskelbėte Object ) - tai gali atrodyti trivialus, tačiau tai mažai dinamiška kalbos, pvz., C++ . Išplėstinis naudojimas leidžia išvardyti ir skambinti metodais, konstruktoriais ir kt.

border=0

Refleksija yra svarbi, nes ji leidžia jums rašyti programas, kurių nereikia „žinoti“ kompiliavimo metu, kad jos taptų dinamiškesnės, nes jas galima susieti vykdymo metu. Kodas gali būti parašytas prieš žinomas sąsajas, tačiau faktinės naudojamos klasės gali būti sukurtos naudojant konfigūracijos failų atspindį.

Dėl šios priežasties daugelis šiuolaikinių sistemų yra plačiai naudojamos. Dauguma kitų šiuolaikinių kalbų taip pat naudoja atspindį, o scenarijų kalbomis (pvz., „Python“) jos yra dar glaudžiau integruotos, nes jos yra labiau natūralios bendrame šių kalbų programavimo modelyje.

207
01 сент. Atsakymas duotas Liedmanui rugsėjo 1 d. 2008-09-01 11:52 '08 at 11:52 2008-09-01 11:52

Vienas iš mano mėgstamiausių atspindžių yra žemiau pateiktas sąvartynų metodas. Kiekvienam objektui priskiriamas parametras ir naudojamas „Java“ atspindžio API spausdinti kiekvieną pavadinimą ir lauko vertę.

 import java.> 
93
02 сент. Atsakymą pateikė Ben Williams 02 Sep. 2008-09-02 19:15 '08 at 7:15 pm 2008-09-02 19:15

Naudokite atspindžius

Refleksiją paprastai naudoja programos, kurios reikalauja išnagrinėti arba pakeisti „Java“ virtualioje mašinoje veikiančių programų veikimo aplinkos elgseną. Tai yra palyginti pažangi funkcija ir ją turėtų naudoti tik kūrėjai, kurie gerai supranta kalbos pagrindus. Atsižvelgiant į šį atsargumą, refleksija yra galingas metodas ir gali leisti paraiškoms atlikti operacijas, kurios kitaip nebūtų įmanoma.

Plėtimo galimybės

Programa gali naudoti išorines pasirinktines klases, sukurdama išplėtimo objektų egzempliorius, naudodama jų visiškai kvalifikuotus pavadinimus. Klasių naršyklės ir vaizdo kūrimo aplinka Klasės naršyklė turi sugebėti išvardyti klasės narius. Vaizdinės plėtros aplinkoje gali būti naudinga naudoti atspindinčio tipo informaciją, kuri padėtų kūrėjui rašyti tinkamą kodą. Debuggers ir testavimo priemonės Debuggers turėtų turėti galimybę patikrinti privačius narius klasėse. Bandymo diržai gali naudoti refleksiją, kad sistemingai remtų įdiegtas aptikimo API, apibrėžtas klasėje, kad bandymų rinkinyje būtų užtikrintas aukštas kodo aprėpties lygis.

Atspindėjimo stoka

Refleksija yra galinga, bet neturėtų būti naudojama nediskriminuojant. Jei galima atlikti operaciją nenaudojant atspindžių, geriau jį naudoti. Priimant kodą per refleksiją reikėtų atsižvelgti į šias problemas.

  • Našumas

Kadangi refleksija apima tipus, kurie yra dinamiškai išspręsti, kai kurių „Java Virtual Machine“ optimizacijų negalima atlikti. Todėl refleksyvios operacijos yra mažesnės nei jų neatspindinčios kolegos, ir jų reikėtų vengti kodų sekcijose, dažnai naudojamose didelį jautrumą charakteristikoms.

  • Apsaugos apribojimai

Atspindėjimui reikia leidimo vykdymo metu, kuris gali būti trūksta dirbant pagal saugumo kontrolę. Tai svarbu kodui, kuris turi būti vykdomas ribotame saugumo kontekste, pavyzdžiui, „Applet“.

  • Vidaus

Kadangi atspindys leidžia kodui atlikti operacijas, kurios būtų neteisėtos neatspindinčiame kode, pavyzdžiui, kai pasiekiama privataus lauko ir metodų, refleksijos naudojimas gali sukelti netikėtus šalutinius poveikius, kurie gali sukelti kodo disfunkciją ir gali pakenkti perkeliamumui. Atspindintis kodas nutraukia abstrakcijas ir todėl gali pakeisti elgesį atnaujinant platformą.

šaltinis: API atspindys

64
17 окт. Desmond Smith atsakymas, pateiktas spalio 17 d 2014-10-17 14:59 '14, 14:59, 2014-10-17 14:59

Refleksija - tai pagrindinis mechanizmas, leidžiantis programai ar sistemai dirbti su kodu, kuris dar nebuvo parašytas!

Paimkite, pavyzdžiui, tipišką failą web.xml. Jame bus sąrašas servleto elementų, kuriuose yra įmontuotų servletų klasės narių. Servletinis konteineris apdoroja web.xml failą ir sukuria naują kiekvienos servletų klasės pavyzdį per atspindį.

Kitas pavyzdys yra „Java“ API XML analizei (JAXP) . Tais atvejais, kai XML analizatoriaus teikėjas yra prijungtas per žinomas sistemos savybes, naudojamas refleksijos būdu kuriant naujus atvejus.

Galiausiai, pilniausias pavyzdys yra „ Pavasaris“ , kuris naudoja atspindžius, kad sukurtų savo pupeles ir intensyviai naudodamiesi proxy.

36
01 сент. Atsakymas suteiktas įrankių rinkiniui 01 Rugsėjis. 2008-09-01 12:30 '08, 12:30, 2008-09-01 12:30

Ne kiekviena kalba palaiko refleksiją, tačiau principai yra vienodi kalbomis, kurios ją palaiko.

Refleksija yra gebėjimas „atspindėti“ jūsų programos struktūrą. Arba tiksliau. Norėdami peržiūrėti turimus objektus ir klases ir programiškai gauti informaciją apie metodus, laukus ir sąsajas, kurias jie įgyvendina. Taip pat galite pažvelgti į anotacijas.

Tai naudinga daugeliu atvejų. Visur norite dinamiškai prijungti klases prie savo kodo. Daugelis objektų reliacinių žemėlapių naudoja atspindžius, kad galėtų kurti objektus iš duomenų bazių, iš anksto nežinodami, kokie objektai bus naudojami. Įskiepiai yra dar viena vieta, kur yra naudinga refleksija. Šiose situacijose svarbu gebėti dinamiškai įkelti kodą ir nustatyti, ar yra tipų, kurie įgyvendina teisingą sąsają.

32
01 сент. atsakymas duotas Mendelt 01 Sep 2008-09-01 11:50 '08 at 11:50 2008-09-01 11:50

Refleksija leidžia kurti naujus objektus, skambučių metodus ir gauti / nustatyti operacijų klasių kintamiesiems dinaminiu būdu vykdymo metu be išankstinių žinių apie jo įgyvendinimą.

 Class myObjectClass = MyObject.class; Method[] method = myObjectClass.getMethods(); //Here the method takes a string parameter if there is no param, put null. Method method = aClass.getMethod("method_name", String.class); Object returnValue = method.invoke(null, "parameter-value1"); 

Pirmiau pateiktame pavyzdyje nulinis parametras yra objektas, kuriuo norite skambinti šiuo metodu. Jei metodas yra statinis, siunčiate nulį. Jei metodas nėra statinis, tada skambinant turite nurodyti galiojantį „MyObject“ pavyzdį vietoj null.

Atspindėjimas taip pat leidžia jums pasiekti privataus klasės narį / metodus:

 public class A{ private String str= null; public A(String str) { this.str= str; } } 

.

 A obj= new A("Some value"); Field privateStringField = A.class.getDeclaredField("privateString"); //Turn off access check for this field privateStringField.setAccessible(true); String fieldValue = (String) privateStringField.get(obj); System.out.println("fieldValue = " + fieldValue); 
  • Norėdami išbandyti klases (taip pat žinomas kaip introspekcija), nereikia importuoti atspindžio paketo ( java.> ). Prieiga prie klasės metaduomenų yra įmanoma per java.> .

Refleksija yra labai galinga API, tačiau ji gali sulėtinti taikomąją programą, jei ji naudojama viršijant, nes ji leidžia visų tipų vykdymą.

31
08 июля '13 в 19:12 2013-07-08 19:12 atsakymą pateikė Nikhil Shekhar liepos 13 d., 19:12, 2013-07-08 19:12

Pavyzdys:
Paimkite, pavyzdžiui, nuotolinę programą, kuri suteikia jūsų programai objektą, kurį gaunate naudodamiesi API metodais. Dabar, remiantis objektu, gali tekti atlikti tam tikrą skaičiavimą.
Tiekėjas garantuoja, kad objektas gali būti 3 tipų, ir mes turime atlikti skaičiavimus pagal tai, kokio tipo objektą.
Taigi, mes galime įgyvendinti tris klases, kurių kiekviena turi skirtingą logiką. Akivaizdu, kad objekto informacija yra prieinama vykdymo metu, todėl negalite statiškai koduoti, kad atliktumėte skaičiavimus, todėl refleksija naudojama kuriant klasės objektą, kuris turi būti apskaičiuotas pagal objektą, gautą iš teikėjo.

20
22 июня '12 в 18:35 2012-06-22 18:35 atsakymas pateikiamas human.js birželio 22 d., 12 val. 18:35 val. 2012-06-22 18:35

„Java“ refleksija yra gana galinga ir gali būti labai naudinga. „Java Reflection“ leidžia patikrinti klases, sąsajas, laukus ir metodus vykdymo metu , nežinant klasių, metodų ir pan. Pavadinimų. Kompiliavimo metu. Taip pat galima sukurti naujus objektus, skambučių metodus ir gauti / nustatyti lauko reikšmes naudojant atspindį.

Greitas „Java“ svarstymo pavyzdys, rodantis, ką naudoja refleksija:

 Method[] methods = MyObject.class.getMethods(); for(Method method : methods){ System.out.println("method = " + method.getName()); } 

Šiame pavyzdyje klasės objektas gaunamas iš klasės „MyObject“. Naudojant klasės objektą, pavyzdys gauna metodų sąrašą šioje klasėje, pakartoja metodus ir spausdina jų pavadinimus.

Jame paaiškinama, kaip visa tai veikia.

Keisti . Praėjus beveik metams, aš redaguoju šį atsakymą, kai perskaičiau apie apmąstymus. Gavau dar keletą „Reflection“ būdų.

  • Pavasaris naudoja pupelių konfigūraciją:


 <bean id="someID" class="com.example.Foo"> <property name="someField" value="someValue" /> </bean> 

Kai pavasario kontekstas apdoroja šį <bean>, jis naudos Class.forName (String) su argumentu „com.example.Foo“, kad sukurtų šios klasės egzempliorių.

Tada jis vėl naudoja refleksiją, kad gautų tinkamą setter'į <property> ir nustatytų jo vertę iki nurodytos vertės.

  • „Junit“ naudoja „Reflection“, skirtą privačiam / saugomam metodui patikrinti.

Privatiems metodams

 Method method = targetClass.getDeclaredMethod(methodName, argClasses); method.setAccessible(true); return method.invoke(targetObject, argObjects); 

Privatiems laukams

 Field field = targetClass.getDeclaredField(fieldName); field.setAccessible(true); field.set(object, value); 
19
08 сент. Atsakymas pateikiamas VdeX 08 Sep. 2014-09-08 12:40 '14, 12:40 2014-09-08 12:40

Pagal mano supratimą:

Atspindėjimas leidžia programuotojui dinamiškai pasiekti programoje esančius objektus. tai yra, koduojant programą, jei programuotojas nežino apie klasę ar jos metodus, jis gali naudoti šią klasę dinamiškai (vykdymo metu), naudojant atspindį.

Jis dažnai naudojamas scenarijuose, kuriuose dažnai keičiasi klasės pavadinimas. Jei susidaro tokia situacija, programuotojui sunku perrašyti programą ir pakeisti klasės pavadinimą dar kartą.

Vietoj to, naudojant refleksiją, jums reikia nerimauti dėl besikeičiančio klasės pavadinimo.

14
06 февр. Atsakymas pateikiamas pramod 06 Feb. 2012-02-06 08:37 '12 8:37 2012-02-06 08:37

Refleksija yra API, naudojama tirti arba modifikuoti metodų, klasių, sąsajų elgseną vykdymo metu.

  • Reikalingos refleksijos klasės pateikiamos java.> .
  • Refleksija suteikia mums informaciją apie klasę, kuriai priklauso objektas, taip pat apie šios klasės metodus, kuriuos galima atlikti naudojant objektą.
  • Per apmąstymus galime remtis metodais vykdymo metu, neatsižvelgiant į prieigos specifiką, su kuriuo jie naudojami.

java.> ir java.> paketai suteikia klasėms atspindėti java.

Apmąstymą galima naudoti norint gauti informaciją apie -

  • Klasė getClass() metodas naudojamas norint gauti klasės, kuriai priklauso objektas, pavadinimą.

  • Konstruktoriai getConstructors() metodas naudojamas tam, kad gautų tos klasės, kuriai priklauso objektas, bendruosius konstruktorius.

  • Metodai getMethods() metodas naudojamas tam, kad gautų tos klasės, kuriai priklauso objektai, viešuosius metodus.

„Reflection API “ dažniausiai naudojama:

IDE (integruota plėtros aplinka). „Eclipse“, „MyEclipse“, „NetBeans“ ir kt.
Derinimo ir bandymo įrankiai ir tt

2019

paprastas pavyzdys atspindėti. Šachmatų žaidime jūs nežinote, ką naudotojas judės vykdymo metu. atspindys gali būti naudojamas skambinti metodais, kurie jau įgyvendinami vykdymo metu.

 public class Test { public void firstMoveChoice(){ System.out.println("First Move"); } public void secondMOveChoice(){ System.out.println("Second Move"); } public void thirdMoveChoice(){ System.out.println("Third Move"); } public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { Test test = new Test(); Method[] method = test.getClass().getMethods(); //firstMoveChoice method[0].invoke(test, null); //secondMoveChoice method[1].invoke(test, null); //thirdMoveChoice method[2].invoke(test, null); } } 
13
06 нояб. Isuru Jayakantha atsakymas lapkričio 06 d 2014-11-06 07:42 '14 at 7:42 2014-11-06 07:42

Refleksija yra funkcijų rinkinys, leidžiantis pasiekti informaciją apie programos vykdymo laiką ir pakeisti jo elgesį (kai kuriais apribojimais).

Tai naudinga, nes ji leidžia keisti elgesį veikimo metu, priklausomai nuo jūsų programos meta informacijos, ty galite patikrinti funkcijos grąžinimo tipą ir pakeisti situacijos tvarkymo būdą.

Pavyzdžiui, C #, galite įkelti surinkimą (DLL) vykdymo metu, patikrinti jį, naršyti per klases ir imtis veiksmų pagal tai, ką radote. Jis taip pat leidžia jums sukurti klasės egzempliorių vykdymo metu, skambinti jo metodu ir tt

Kur tai gali būti naudinga? Ne visada naudinga, bet konkrečioms situacijoms. Pavyzdžiui, galite jį naudoti, kad gautumėte klasės pavadinimą loggin tikslams, kad būtų galima dinamiškai kurti įvykių tvarkytojus pagal tai, kas nurodyta konfigūracijos faile ir tt

13
01 сент. Jorge Córdoba atsakymas, pateiktas rugsėjo 1 d 2008-09-01 11:50 '08 at 11:50 2008-09-01 11:50

Atspindys - leiskite objektui matyti jų išvaizdą. Šis argumentas neturi nieko bendro su mąstymu. Tiesą sakant, tai yra gebėjimas „save identifikuoti“.

Atspindėjimas yra žodis kalboms, neturinčioms savęs pažinimo ir gerovės, pavyzdžiui, „Java“ ir „C #“. Kadangi jie nesugeba savęs pažinti, kai norime stebėti, kaip atrodo, turime galvoti apie tai, kaip atrodo. Puikios dinamiškos kalbos, pvz., Ruby ir Python, gali atsispindėti be kitų žmonių pagalbos. Galima sakyti, kad „Java“ objektas negali suvokti, kaip jis atrodo be veidrodžio, kuris yra atspindžio klasės objektas, bet Python objektas gali jį suvokti be veidrodžio. Todėl turime galvoti apie „Java“.

10
08 дек. Atsakymą pateikė Marcus Thornton. 2015-12-08 10:02 '15 at 10:02 am 2015-12-08 10:02

Java“ dokumentacijos puslapyje

Пакет java.> предоставляет классы и интерфейсы для получения отражающей информации о классах и объектах. Reflection позволяет программный доступ к информации о полях, методах и конструкторах загруженных классов и использование отраженных полей, методов и конструкторов для работы с их базовыми аналогами в рамках ограничений безопасности.

AccessibleObject позволяет подавлять проверки доступа, если имеется необходимый ReflectPermission .

Классы в этом пакете наряду с java.> включают приложения, такие как отладчики, интерпретаторы, инспекторы объектов, браузеры классов и сервисы, такие как Object Serialization и JavaBeans которым нужен доступ либо к публичным членам целевого объекта (на основе его runtime class) или членов, объявленных данным классом