Што такое адлюстраванне і чаму яно карысна?

Што такое адлюстраванне і чаму яно карысна?

Мяне асабліва цікавіць Java, але я мяркую, што прынцыпы аднолькавыя на любой мове.

1812
01 сент. зададзены Lehane 01 сент. 2008-09-01 11:39 '08 у 11:39 2008-09-01 11:39
ответ 21 адказ

Адлюстраванне назвы выкарыстоўваецца для апісання кода, які здольны правяраць іншы код у той жа сістэме (або сам).

Напрыклад, выкажам здагадку, што ў вас ёсць аб'ект невядомага тыпу ў Java, і вы хочаце называць яго метадам doSomething, калі ён існуе. Статычная сістэма тыпізацыі Java на самай справе не прызначана для падтрымкі гэтага, калі аб'ект не адпавядае вядомаму інтэрфейсу, але, выкарыстоўваючы адлюстраванне, ваш код можа глядзець на аб'ект і высветліць, ці ёсць у яго метад "doSomething", а затым выклікаць яго, калі вы хацець.

Такім чынам, каб даць вам прыклад кода гэтага ў Java (выкажам здагадку, што аб'ект, пра які ідзе гаворка, з'яўляецца foo):

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

Адным з распаўсюджаных прыкладаў выкарыстання Java з'яўляецца выкарыстанне анатацый. Напрыклад, JUnit 4 будзе выкарыстоўваць рэфлексію для прагляду вашых класаў для метадаў, пазначаных анатацыяй @Test, і затым выкліча іх пры запуску модульнага тэсту.

Ёсць некалькі добрых прыкладаў адлюстравання, якія дапамогуць вам пачаць працу па адрасе http://docs.oracle.com/javase/tutorial/reflect/index.html.

І, нарэшце, ды, паняцці вельмі падобныя на іншыя мовы статычнага тыпу, якія падтрымліваюць адлюстраванне (напрыклад, З #). У дынамічна тыпізаваных мовах апісаны вышэй варыянт выкарыстання менш неабходны (паколькі кампілятар дазваляе выклік любога метаду на любы аб'ект, калі ён не выконваецца падчас выканання, калі ён не існуе), але другі выпадак пошуку метадаў, якія адзначаны ці праца ў пэўным сэнсе ўсё яшчэ распаўсюджана.

Абнаўленне ад каментара:

Здольнасць правяраць код у сістэме і бачыць тыпы аб'ектаў не з'яўляецца адлюстраваннем, а хутчэй уяўляе сабой Introspection. Адлюстраванне - гэта здольнасць ўносіць змены ў час выканання, выкарыстоўваючы інтраспекцыі. Адрозненне неабходна тут, паколькі некаторыя мовы падтрымліваюць самааналіз, але не падтрымліваюць рэфлексію. Адным з такіх прыкладаў з'яўляецца C ++

1500
01 сент. адказ дадзены Matt Sheppard 01 сент. 2008-09-01 11:44 '08 у 11:44 2008-09-01 11:44

Адлюстраванне - гэта здольнасць мовы правяраць і дынамічна выклікаць класы, метады, атрыбуты і г.д. падчас выканання.

Напрыклад, усе аб'екты ў Java маюць метад getClass() , які дазваляе вызначыць клас аб'екта, нават калі вы не ведаеце яго падчас кампіляцыі (напрыклад, калі вы абвясцілі яго як Object ) - гэта можа здаюцца трывіяльнымі, але такое адлюстраванне немагчыма ў менш дынамічных мовах, такіх як C++ . Больш пашыранае выкарыстанне дазваляе вам пералічыць і выклікаць метады, канструктары і г.д.

border=0

Адлюстраванне важна, паколькі яно дазваляе вам пісаць праграмы, якія не павінны "ведаць" усё падчас кампіляцыі, робячы іх больш дынамічнымі, так як яны могуць быць звязаныя падчас выканання. Код можа быць напісаны супраць вядомых інтэрфейсаў, але фактычныя класы, якія будуць выкарыстоўвацца, могуць быць створаны з выкарыстаннем адлюстравання ад файлаў канфігурацыі.

Мноства сучасных фреймворков шырока выкарыстоўваюць рэфлексію менавіта па гэтай прычыне. Большасць іншых сучасных моў таксама выкарыстоўваюць адлюстраванне, а ў мовах сцэнарыяў (напрыклад, Python) яны яшчэ больш цесна інтэграваныя, паколькі яны больш натуральныя ў агульнай мадэлі праграмавання гэтых моў.

207
01 сент. адказ дадзены Liedman 01 сент. 2008-09-01 11:52 '08 у 11:52 2008-09-01 11:52

Адно з маіх любімых адлюстраванняў - метад дампа ніжэй. Ён прымае любы аб'ект у якасці параметру і выкарыстоўвае API адлюстравання Java для раздрукоўкі кожнага імя і значэння поля.

 import java.> 
93
02 сент. адказ дадзены Ben Williams 02 сент. 2008-09-02 19:15 '08 у 19:15 2008-09-02 19:15

выкарыстанне адлюстраванняў

Адлюстраванне звычайна выкарыстоўваецца праграмамі, якія патрабуюць магчымасці даследаваць або змяняць паводзіны асяроддзя выканання прыкладанняў, запушчаных на віртуальнай машыне Java. Гэта адносна прасунутая функцыя і павінна выкарыстоўвацца толькі распрацоўшчыкамі, якія добра разумеюць асновы мовы. Улічваючы гэта перасцярога, рэфлексія з'яўляецца магутным метадам і можа дазволіць прыкладанням выконваць аперацыі, якія ў адваротным выпадку былі б немагчымыя.

магчымасці пашырэння

Прыкладанне можа выкарыстоўваць знешнія прыстасаваныя класы, ствараючы асобнікі аб'ектаў пашыральнасці, выкарыстоўваючы іх цалкам кваліфікаваныя імёны. Браўзэры класаў і асяроддзя візуальнага развіцця Браўзэр класаў павінен мець магчымасць пералічваць члены класаў. Візуальныя асяроддзя распрацоўкі могуць атрымаць выгаду з выкарыстання інфармацыі тыпу, даступнай для разважання, каб дапамагчы распрацоўніку ў напісанні правільнага кода. Адладчык і сродкі тэставання адладчык павінны мець магчымасць правяраць прыватных членаў у класах. Тэставыя джгуты могуць выкарыстоўваць рэфлексію для сістэматычнага выкліку устаноўленых API-інтэрфейсаў выяўлення, вызначаных у класе, для забеспячэння высокага ўзроўню ахопу кода ў наборы тэстаў.

недахопы адлюстравання

Адлюстраванне магутна, але не павінна выкарыстоўвацца без разбору. Калі можна выканаць аперацыю без выкарыстання адлюстравання, то пераважна пазбягаць яе выкарыстання. Наступныя праблемы варта ўлічваць пры доступе да кода праз адлюстраванне.

  • прадукцыйнасць

Паколькі адлюстраванне ўключае тыпы, якія дынамічна дазволеныя, некаторыя аптымізацыі віртуальнай машыны Java не могуць быць выкананыя. Такім чынам, рэфлексіўных аперацыі маюць больш нізкую прадукцыйнасць, чым іх неотражающие аналагі, і іх варта пазбягаць ў раздзелах кода, якія часта выкарыстоўваюцца ў прыкладаннях з высокай адчувальнасцю да характарыстыках.

  • абмежаванні бяспекі

Для адлюстравання патрабуецца дазвол падчас выканання, якое можа адсутнічаць пры працы пад кіраваннем бяспекі. Гэта важна для кода, які павінен выконвацца ў абмежаванай кантэксце бяспекі, напрыклад, у Applet.

  • ўздзеянне ўнутраных

Паколькі адлюстраванне дазваляе коду выконваць аперацыі, якія былі б незаконнымі ў неотражающем кодзе, напрыклад, пры доступе да прыватных палях і метадам, выкарыстанне рэфлексіі можа прывесці да нечаканых пабочным эфектам, што можа прывесці да дысфункцыі кода і можа прывесці да пашкоджання пераноснасці. Адлюстроўвае код разбівае абстракцыі і таму можа змяняць паводзіны падчас абнаўлення платформы.

крыніца: API Reflection

64
17 окт. адказ дадзены Desmond Smith 17 каст. 2014-10-17 14:59 '14 у 14:59 2014/10/17 14:59

Адлюстраванне - ключавы механізм, які дазваляе з дадаткам або фреймворка працаваць з кодам, які, магчыма, яшчэ не быў напісаны!

Возьмем, да прыкладу, ваш тыповы файл web.xml. Гэта будзе змяшчаць спіс элементаў сэрвлета, якія ўтрымліваюць укладзеныя элементы класа сэрвлета. Кантэйнер сэрвлета апрацоўвае файл web.xml і стварае новы асобнік кожнага класа сэрвлета з дапамогай адлюстравання.

Іншым прыкладам можа служыць Java API для аналізу XML (JAXP) . Дзе пастаўшчык XML-парсераў "падлучаны" праз вядомыя сістэмныя ўласцівасці, якія выкарыстоўваюцца для стварэння новых асобнікаў з дапамогай адлюстравання.

І нарэшце, найбольш поўным прыкладам з'яўляецца Spring , які выкарыстоўвае адлюстраванне для стварэння свайго beans і для яго інтэнсіўнага выкарыстання проксі

36
01 сент. адказ дадзены toolkit 01 сент. 2008-09-01 12:30 '08 ў 12.30 2008-09-01 00:30

Не кожны мова падтрымлівае адлюстраванне, але прынцыпы звычайна аднолькавыя на мовах, якія яго падтрымліваюць.

Адлюстраванне - гэта здольнасць "адлюстроўваць" структуру вашай праграмы. Або больш канкрэтны. Каб бачыць аб'екты і класы, якія ў вас ёсць, і праграмна атрымаць інфармацыю аб метадах, палях і інтэрфейсах, якія яны рэалізуюць. Вы таксама можаце паглядзець на такія рэчы, як анатацыі.

Гэта карысна ў многіх сітуацыях. Усюды вы хочаце дынамічна падключаць класы да вашага коду. Мноства аб'ектных рэляцыйных карт выкарыстоўваюць адлюстраванне, каб мець магчымасць ствараць аб'екты з баз даных, не ведаючы загадзя, якія аб'екты яны будуць выкарыстоўваць. Убудовы - гэта яшчэ адно месца, дзе карысна выкарыстоўваць адлюстраванне. Магчымасць дынамічна загружаць код і вызначаць, ці існуюць там тыпы, якія рэалізуюць правільны інтэрфейс для выкарыстання ў якасці ўбудовы, важныя ў гэтых сітуацыях.

32
01 сент. адказ дадзены Mendelt 01 сент. 2008-09-01 11:50 '08 у 11:50 2008-09-01 11:50

Адлюстраванне дазваляе ствараць новыя аб'екты, выклікаць метады і атрымліваць / ўсталёўваць аперацыі над зменнымі класа дынамічна падчас выканання без папярэдняга веды яго рэалізацыі.

 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"); there is no param 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"); 

У прыведзеным вышэй прыкладзе нулявы параметр - гэта аб'ект, на які вы жадаеце выклікаць метад. Калі метад статычны, вы адпраўляеце нуль. Калі метад не з'яўляецца статычным, то пры выкліку вам трэба паказаць сапраўдны экзэмпляр MyObject замест null.

Reflection таксама дазваляе вам атрымаць доступ да прыватнаму члену / метадам класа:

 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); 
  • Для праверкі класаў (таксама вядомых як інтраспекцыя) вам не трэба імпартаваць пакет адлюстравання ( java.> ). Доступ да метададзеных класа магчымы праз java.> .

Reflection - вельмі магутны API, але ён можа запаволіць працу прыкладання, калі ён выкарыстоўваецца ў лішку, паколькі ён дазваляе ўсе тыпы падчас выканання.

31
08 июля '13 в 19:12 2013-07-08 19:12 адказ дадзены Nikhil Shekhar 08 ліпеня '13 ў 19:12 2013/07/08 19:12

прыклад:
Вазьміце, напрыклад, выдаленае прыкладанне, якое дае вашаму з дадаткам аб'ект, які вы атрымліваеце, выкарыстоўваючы іх метады API. Цяпер, грунтуючыся на аб'екце, вам можа спатрэбіцца выканаць нейкае вылічэнне.
Пастаўшчык гарантуе, што аб'ект можа мець 3 тыпу, і нам трэба выканаць вылічэнні на аснове таго, які тып аб'екта.
Такім чынам, мы можам рэалізаваць у 3 класах, кожны з якіх змяшчае іншую логіку. Відавочна, інфармацыя аб аб'екце даступная падчас выканання, таму вы не можаце статычна кадзіраваць для выканання вылічэнняў, таму адлюстраванне выкарыстоўваецца для стварэння аб'екта класа, які патрабуецца выканаць вылічэнне на аснове аб'екта, атрыманага ад пастаўшчыка.

20
22 июня '12 в 18:35 2012-06-22 18:35 адказ дадзены human.js 22 чэрвеня '12 у 18:35 2012-06-22 18:35

Java Reflection даволі магутны і можа быць вельмі карысным. Java Reflection дазваляе правяраць класы, інтэрфейсы, палі і метады падчас выканання,, не ведаючы імёны класаў, метадаў і г.д. Падчас кампіляцыі. Таксама магчыма ствараць новыя аб'екты, выклікаць метады і атрымліваць / ўсталёўваць значэння палёў з дапамогай адлюстравання.

Хуткі прыклад Java Reflection, каб паказаць вам, што выкарыстоўвае адлюстраванне:

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

У гэтым прыкладзе атрыманы аб'ект класа з класа MyObject. Выкарыстоўваючы аб'ект класа, прыклад атрымлівае спіс метадаў у гэтым класе, выконвае ітэрацыі метадаў і раздрукоўвае іх імёны.

Менавіта тут тлумачыцца, як усё гэта працуе

Змяніць. Амаль праз год я рэдагую гэты адказ, калі чытаю аб адлюстраванні. Я атрымаў яшчэ некалькі ужыванняў Reflection.

  • Spring выкарыстоўвае канфігурацыю bean, такую ​​як:


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

Калі кантэкст Spring апрацоўвае гэты <bean>, ён будзе выкарыстоўваць Class.forName (String) з аргументам "com.example.Foo" для стварэння асобніка гэтага класа.

Затым ён зноў выкарыстоўвае адлюстраванне, каб атрымаць адпаведны сетэр для <property> і ўсталюйце яго значэнне ў названае значэнне.

  • Junit выкарыстоўвае Reflection спецыяльна для тэставання прыватных / абароненых метадаў.

Для прыватных метадаў

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

Для прыватных палёў

 Field field = targetClass.getDeclaredField(fieldName); field.setAccessible(true); field.set(object, value); 
19
08 сент. адказ дадзены VdeX 08 сент. 2014-09-08 12:40 '14 а 12.40 2014/09/08 00:40

У адпаведнасці з маім разуменнем:

Адлюстраванне дазваляе праграмісту дынамічна звяртацца да аб'ектаў у праграме. гэта значыць пры кадаванні прыкладання, калі праграміст не ведае пра клас або яго метадах, ён можа выкарыстоўваць гэты клас дынамічна (падчас выканання) з дапамогай адлюстравання.

Ён часта выкарыстоўваецца ў сцэнарах, дзе імя класа часта мяняецца. Калі такая сітуацыя ўзнікае, то праграмісту складана перазапісаць прыкладанне і змяніць імя класа зноў і зноў.

Замест гэтага, выкарыстоўваючы рэфлексію, трэба турбавацца аб магчыма зменлівым імя класа.

14
06 февр. адказ дадзены pramod 06 февр. 2012-02-06 08:37 '12 у 08:37 2012-02-06 08:37

Адлюстраванне - гэта API, які выкарыстоўваецца для вывучэння або змены паводзін метадаў, класаў, інтэрфейсаў падчас выканання.

  • Неабходныя класы для адлюстравання прадастаўляюцца пад java.> .
  • Reflection дае нам інфармацыю пра клас, да якога належыць аб'ект, а таксама аб метадах гэтага класа, якія могуць быць выкананы з выкарыстаннем аб'екта.
  • Праз адлюстраванне мы можам спасылацца на метады падчас выканання, незалежна ад выкарыстоўванага з імі спецификатора доступу.

Пакеты java.> і java.> прадастаўляюць класы для адлюстравання java.

Адлюстраванне можна выкарыстоўваць для атрымання інфармацыі аб -

  • Клас Метад getClass() выкарыстоўваецца для атрымання імя класа, да якога належыць аб'ект.

  • Канструктары Метад getConstructors() выкарыстоўваецца для атрымання агульных канструктараў класа, да якога належыць аб'ект.

  • Метады Метад getMethods() выкарыстоўваецца для атрымання агульнадаступных метадаў класа, да якога належаць аб'екты.

Reflection API выкарыстоўваецца ў асноўным:

IDE (інтэграванае асяроддзе распрацоўкі), напрыклад. Eclipse, MyEclipse, NetBeans і г.д.
Адладчык і тэставыя прылады і г.д.

2019

просты прыклад для адлюстравання. У шахматнай гульні вы не ведаеце, што будзе перамешчана карыстальнікам падчас выканання. адлюстраванне можна выкарыстоўваць для выкліку метадаў, якія ўжо рэалізаваны падчас выканання.

 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 06 лістапада. 2014-11-06 07:42 '14 у 07:42 2014/11/06 07:42

Reflection - гэта набор функцый, які дазваляе вам атрымліваць доступ да інфармацыі пра час выканання вашай праграмы і змяняць яе паводзіны (з некаторымі абмежаваннямі).

Гэта карысна, таму што гэта дазваляе вам змяняць паводзіны падчас выканання ў залежнасці ад метаінформаціі вашай праграмы, гэта значыць вы можаце праверыць тып звароту функцыі і змяніць спосаб апрацоўкі сітуацыі.

У З #, напрыклад, вы можаце загружаць зборку (DLL) у час выканання, правяраць яе, перамяшчацца па класах і прымаць дзеянні ў адпаведнасці з тым, што вы знайшлі. Ён таксама дазваляе ствараць асобнік класа падчас выканання, выклікаць яго метад і г.д.

Дзе гэта можа быць карысна? Няма карысьці кожны раз, але для канкрэтных сітуацый. Напрыклад, вы можаце выкарыстоўваць яго для атрымання імя класа для мэтаў loggin, каб дынамічна ствараць апрацоўшчыкі для падзей у адпаведнасці з тым, што паказана ў файле канфігурацыі і г.д.

13
01 сент. адказ дадзены Jorge Córdoba 01 сент. 2008-09-01 11:50 '08 у 11:50 2008-09-01 11:50

Адлюстраванне - дазволіць аб'екту ўбачыць іх знешні выгляд. Гэты аргумент не мае ніякага дачынення да разважання. Фактычна, гэта здольнасць "ідэнтыфікаваць сябе".

Сама рэфлексія - гэта слова для такіх моў, якія не валодаюць здольнасцю да самапазнання і самаадчуванню як Java і З #. Паколькі ў іх няма магчымасці самапазнання, калі мы хочам назіраць, як гэта выглядае, у нас павінна быць іншая справа, каб падумаць пра тое, як гэта выглядае. Выдатныя дынамічныя мовы, такія як Ruby і Python, могуць успрымаць сваё адлюстраванне без дапамогі іншых людзей. Можна сказаць, што аб'ект Java не можа ўспрымаць, як гэта выглядае без люстэрка, якое з'яўляецца аб'ектам класа адлюстравання, але аб'ект у Python можа ўспрымаць яго без люстэрка. Таму нам трэба разважаць на Java.

10
08 дек. адказ дадзены Marcus Thornton 08 снеж. 2015-12-08 10:02 '15 у 10:02 2015/12/08 10:02

На старонцы дакументацыі java

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

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

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