Reflexe_02. Přístup k datovým atributům třídy pomocí reflexe

Podobné dokumenty
UJO Framework. revoluční architektura beans. verze

Reflexe. Aplikační programování v Javě (BI-APJ) - 8 Ing. Jiří Daněček Katedra softwarového inženýrství Fakulta informačních technologií ČVUT Praha

Reflexe RTTI Runtime Type Identification

typová konverze typová inference

JAVA. Reflection API

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

Úvod do programovacích jazyků (Java)

Obsah přednášky 7. Základy programování (IZAPR) Přednáška 7. Parametry metod. Parametry, argumenty. Parametry metod.

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Reflexe_03. Používání dynamického proxy

Výčtový typ strana 67

Class loader. každá třída (java.lang.class) obsahuje referenci na svůj class loader. Implementace class loaderu

7. přednáška - třídy, objekty třídy objekty atributy tříd metody tříd

Teoretické minimum z PJV

Počítačové laboratoře bez tajemství aneb naučme se učit algoritmizaci a programování s využitím robotů CZ.1.07/1.3.12/

SOUBORY, VSTUPY A VÝSTUPY POKRAČOVÁNÍ

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

SW_06. Reflexe (reflection)

8. přednáška: Soubory a proudy

RMI Remote Method Invocation

Java a XML. 10/26/09 1/7 Java a XML

Abstraktní datové typy: zásobník

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Vytváření a použití knihoven tříd

Pokročilé programování na platformě Java. Úvod

PŘETĚŽOVÁNÍ OPERÁTORŮ

8 Třídy, objekty, metody, předávání argumentů metod

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

Bridge. Známý jako. Účel. Použitelnost. Handle/Body

Úvod Třídy Rozhraní Pole Konec. Programování v C# Hodnotové datové typy, řídící struktury. Petr Vaněček 1 / 39

Soubor jako posloupnost bytů

Remote Method Invocation RMI

Generické programování

Statické proměnné a metody. Tomáš Pitner, upravil Marek Šabo

Programování v Javě I. Leden 2008

Programování v Javě I. Únor 2009

Seznamy a iterátory. Kolekce obecně. Rozhraní kolekce. Procházení kolekcí

Seminář Java II p.1/43

4. ZÁKLADNÍ POJMY Z OBJEKTOVĚ ORIENTOVANÉHO PROGRAMOVÁNÍ

Seminář Java IV p.1/38

Předmluva k aktuálnímu vydání Úvod k prvnímu vydání z roku Typografické a syntaktické konvence... 20

KTE / ZPE Informační technologie

PREPROCESOR POKRAČOVÁNÍ

1. Programování proti rozhraní

O autorovi O odborném korektorovi Úvod 17 Vývoj jazyka Java Java SE 8 Struktura této knihy Předchozí zkušenosti s programováním nejsou potřebné

20. Projekt Domácí mediotéka

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

public static void main(string[] args) { System.out.println(new Main().getClass().getAnnotation(Greet.class).text());

Java Výjimky Java, zimní semestr

Definice třídy. úplná definice. public veřejná třída abstract nesmí být vytvářeny instance final nelze vytvářet potomky

Programátorská příručka

Google Web Toolkit. Martin Šurkovský, SUR března Katedra informatiky

Algoritmizace a programování

Z. Kotala, P. Toman: Java ( Obsah )

7. Dynamické datové struktury

Třídy, polymorfismus. A0B36PR2-Programování 2 Fakulta elektrotechnická České vysoké učení technické

9. přednáška - třídy, objekty

Java a Caché IV: Manipulace s objekty

Soketové připojení Klient InetAddress getbyname() UnknowHostException SecurityException Socket getinputstream() getoutputstream() IOException Server

Úvod do programovacích jazyků (Java)

Zapouzdření. Tomáš Pitner, upravil Marek Šabo

Projekty pro výuku programování v jazyce Java

RMI - Distribuované objekty v Javě

Obsah přednášky 9. Skrývání informací. Skrývání informací. Zapouzdření. Skrývání informací. Základy programování (IZAPR, IZKPR) Přednáška 9

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

Třídy a objekty. Třídy a objekty. Vytvoření instance třídy. Přístup k atributům a metodám objektu. $z = new Zlomek(3, 5);

OOPR_05. Případové studie

Využití OOP v praxi -- Knihovna PHP -- Interval.cz

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

OMO. 4 - Creational design patterns A. Singleton Simple Factory Factory Method Abstract Factory Prototype Builder IoC

17. Projekt Trojúhelníky

Anotace a Hibernate. Aleš Nosek Ondřej Vadinský Daniel Krátký

Jazyk C# (seminář 6)

Třídy. Instance. Pokud tento program spustíme, vypíše následující. car1 má barvu Red. car2 má barvu Red. car1 má barvu Blue.

1. Téma 12 - Textové soubory a výjimky

Abstraktní třída a rozhraní

Základy Guice Vazby Scopes. Google Guice. základní seznámení s frameworkem Google Guice

TÉMATICKÝ OKRUH Softwarové inženýrství

Dědičnost (inheritance)

Programování v C++ 2, 4. cvičení

Programování v C++ 1, 5. cvičení

Úvod. Často jsme nuceni řešit problémy, které by reflexe řešila jasněji, stabilněji a přehledněji. Změny v požadavcích na programové vybavení

Katedra měřicí a řídicí techniky, VŠB - Technická univerzita v Ostravě, tř. 17. listopadu, Ostrava-Poruba, Česká republika

TÉMATICKÝ OKRUH Softwarové inženýrství

Datové struktury. alg12 1

Úvod do programovacích jazyků (Java)

První kapitola úvod do problematiky

Vláknové programování část V

Java Řetězce Java, zimní semestr

Typický prvek kolekce pro české řazení

Kód, který se nebude často měnit

TŘÍDY POKRAČOVÁNÍ. Události pokračování. Příklad. public delegate void ZmenaSouradnicEventHandler (object sender, EventArgs e);

Objektově orientované programování v PHP 5. Martin Klíma

Java - výjimky. private void vstup() throws IOException {... }

Pokud zadání nerozumíte nebo se vám zdá nejednoznačné, zeptejte se. Pište čitelně, nečitelná řešení nebudeme uznávat.

3. Třídy. Základní pojmy objektového programování. Třídy

Objekty v PHP 5.x. This is an object-oriented system. If we change anything, the users object.

Principy objektově orientovaného programování

IRAE 07/08 Přednáška č. 2. atr1 atr2. atr1 atr2 -33

Úvod do programování - Java. Cvičení č.4

Transkript:

Reflexe_02 Přístup k datovým atributům třídy pomocí reflexe

Přístup k datovým atributům třídy pomocí reflexe využití prozkoumání rozhraní, prozkoumání datových atributů, přístup a modifikace datových atributů, přístup k neveřejným (non public) datovým atributům. 2

Testování serializovatelnosti Testing for Serializability příklad testuje, zda třída objektu, nebo libovolná nadtřída implementovala rozhraní Serializable pomocná třída má pouze statickoumetodu isserializable() SerializableTester.isSerializable( java.util.calendar.getinstance()); SerializableTester.isSerializable( new Object());

import java.io.serializable; public class SerializableTester { private static final String serial = "java.io.serializable"; public static boolean isserializable( Object obj ) { if ( obj == null ) return false; Class c = obj.getclass(); do { Class[ ] ifaces = c.getinterfaces(); for ( int i = 0; i < ifaces.length; i++ ) if ( serial.equals( ifaces[ i ].getname() ) ) return true; c = c.getsuperclass(); while ( c!= null ); // cykluj, dokud trida je Object return false; Metoda getclass() deklarovaná ve třídě Object metoda getinterface() vrací pole rozhraní metoda getsuperclass() vrací nadtřídu 4

public class SerializableTest { public static void main(string[] args) { boolean q = SerializableTester.isSerializable( java.util.calendar.getinstance()); if(q) System.out.println("Calendar je serializovatelny"); else System.out.println("Calendar neni serializovatelny"); q = SerializableTester.isSerializable(new Object()); if(q) System.out.println("Object je serializovatelny"); else System.out.println("Object neni serializovatelny"); Výpis Calendar je serializovatelný Object není serializovatelný 5

Serializaceobjektů Uložení a rekonstrukce objektů z binárního formátu. Výhody pro uživatelskou serializaci: binární formát zobrazit ve web prohlížeči, nutnost implementace rozhraní Serializable problém third-part libraries, neimplementují rozhraní, použití serializacepouze uvnitř platformy Java. 6

Serializacedo XML použití XML jako formátu serializaceřeší všechny předchozí nevýhody obecná podpora XML element: <zoo> <animal>panda</animal> <animal>giraffe</animal> </zoo> <tag-name attribute-name= attribute value /> 7

Serializacedo XML soubor, řetězecnebostream zpracovaný podle XML dokument dokument má rootelement (kořenový element) 8

Návrh serializaces využitím reflexe metoda serializeobject(object) serializuje parametr - podmínky 1. získat serializovaný objekt parametr metody, 2. nalézt deklarovanou třídu objektu a jména datových atributů, 3. získat hodnotu každého datového atributu, 4. je-li datový atribut objektem, který nebyl serializovaný, provést jeho serializaci, 5. primitivní atribut uložit, aby byl snadno obnovený. 9

Získání datových atributů za běhu Metoda Popis Field getfield(string name) Vrátíobjekt Field, který představuje specifikovaný public atribut třídy nebo rozhraní podle objektu třídy (Class objektu) Field[] getfields() Field getdeclaredfield( String name) Vrací pole objektůfield, které představují všechny přístupné public atributy třídy nebo rozhraní podle objektu třídy (Class objektu) Vrací objekt Field, který představuje specifikovaný deklarovaný atribut třídy nebo rozhraní, reprezentovaný tímto objektem třídy Field[] getdeclaredfields() Vrací pole objektůfield, které představují každý deklarovaný atribut třídy nebo rozhraní tohoto objektu třídy. 10

Class cls = obj.getclass(); List accum = new LinkedList(); while (cls!= null) { Field[] f = cls.getdeclaredfields(); for(int i=0; i< f.length; i++) { accum.add(f[i]); cls = cls.getsuperclass(); Field[] allfields = (Field[]) accum.toarray(new Field[accum.size()]); Podstatná část kódu, která řeší problém 11

Pochopení objektů datových atributů Datový atribut specifikovaný jménem třídy a jménem atributu řeší stejná jména atributů v nadtřídách. getdeclaredfirlds()vrací objekt java.lang.reflect.field. MetaobjektFieldpředstavuje konkrétní datový atribut třídy. MetaobjektFieldposkutujemetadatao jménu atributu, deklarované třídy a modifikátorech. 12

Metody metaobjektufield Metoda Class gettype() Popis Vrací objekt Class, který představuje deklarovaný typ pro datový atribut, reprezentovaný tímto objektem Field. Class getdecklaringclass() Vrací objekt Class, který deklaroval atribut reprezentovaný tímto objektem Field. String getname() int getmodifiers() Object get(object obj) Booealn getboolean(object obj) Vrací jméno datového atributu reprezentovaného tímto objektem Field. Vrací modifikátorypro datový atribut reprezentovaný tímto objektem Field, kódovaným do int. Vrací hodnotu specifikovaného objektu atributu reprezentovaného pomocí tohoto objektu Field. Vrací hodnotu specifikovaného objektu boolovskéhoatributu reprezentovaného tímto Field. 13

MetaobjektField Pokud proměnná fieldukazuje na objekt Field, můžeme dostat hodnoty, které ji jednoznačně identifikují: String fieldname = field.getname(); String fielddeclclass = field.getdeclaringclass().getname(); 14

Přístupa modifikacehodnot datových atributů get/set metody K úspěšné serializaciobjektu musí být uloženy datové atributy. Pokud fieldodkazuje na objekt fieldodpovídající třídy objektu obj, pak přístup: Object value = field.get(obj); field.set(obj, value); Primitivní typy vrací jako obalové typy. IllegalArgumentException 15

Modifikátory Třídní (statické) atributy nechceme serializovat. V Javě existuje devět modifikátorů: public static native volatile protected abstract synchronize strictfp private final transient 16

Modifikátory statická boolovská metoda pro zjištění: static boolean ispublic(int mod) Vrací true, pokud parametr modmá nastavený bit na ispublic int getmodifiers() Modifier.isStatic(field.getModifiers() ); Vrací true, jedná-li se o třídní modifikátor 17

public static Field[] getinstancevariables(class cls) { List accum = new LinkedList(); while (cls!= null) { Field[] fields = cls.getdeclaredfields(); for (int i=0; i<fields.length; i++) { if (!Modifier.isStatic(fields[i].getModifiers())) { accum.add(fields[i]); cls = cls.getsuperclass(); Field[] retvalue = new Field[accum.size()]; return (Field[]) accum.toarray(retvalue); Závěrečné pole obsahuje množinu netřídních (nestatických) datových atributů třídy 18

Přístup k atributům non-public Kontrola přístupu k datovým atributům nonpublic může být potlačena. To umožní přístup k protected, packagea private. Třída java.lang.reglect.accessibleobjectje rodičovskou třídou pro třídy Field a Method. Třída AccessibleObjectmá metodu setaccessible(), která potlačí/umožní kontrolu. 19

Přístup k atributům non-public field.setaccessible(true); potlačí kontrolu modifikátorů přístupu if (!Modifier.isPublic(field.getModifiers())) { field.setaccessible(true); Object value = field.get(); Vykonánezbytný přístup pro reflektivní serializaci. 20

Metody deklarované objektem AccessibleObject Metoda void setaccessible( boolean flag) booleanisaccessible() static void setaccessible( AccessibleObject[] array, boolean flag) Popis Nastavuje příznakpříjemce na hodnotu danou parametrem. Vrací truepouze tehdy, je-li příznak objektu příjemce true. Nastavuje přístupové příznaky všech prvků pole objektu příjemce. 21

Práce s poli Metoda isarray() třídy Objectodpoví true/false. Pole se obecně přetypovávají na Object[]. Pole primitivních hodnot neumožňují uvedené přetypování. Cesta jak pracovat s poli objektů a primitivních typů jednotně. 22

Práce s poli Třída java.lang.reflect.array vhodný prostředek pro práci s reflexí na polích. int length = Array.getLenght(obj); Zjištění délky pole. Array.get(obj,i); Zpřístupnění daného objektu pole. 23

public static Document serializeobject( Object source ) throws Exception { return serializehelper( source, new Document( new Element("serialized") ), new IdentityHashMap() ); private static Document serializehelper( Object source, Document target, Map table ) throws Exception { String id = Integer.toString( table.size() ); //#1 table.put( source, id ); //#1 Class sourceclass = source.getclass(); //#1 Element oelt = new Element("object"); //#2 oelt.setattribute( "class", sourceclass.getname() ); //#2 oelt.setattribute( "id", id ); //#2 target.getrootelement().addcontent(oelt); //#2 #1Vytváří jedinečný identifikátor objektu pro jeho serializaci. #2 Vytváří element XML pro objekt 24

if (!sourceclass.isarray() ) { //#3 Field[] fields = Mopex.getInstanceVariables(sourceclass); //#4 for (int i=0; i<fields.length; i++) { //#4 if (!Modifier.isPublic(fields[i].getModifiers()) ) //#5 fields[i].setaccessible(true); //#5 Element felt = new Element("field"); //#6 felt.setattribute( "name", fields[i].getname() ); //#6 Class declclass = fields[i].getdeclaringclass(); //#6 felt.setattribute( "declaringclass", //#6 declclass.getname() ); //#6 //#6 Class fieldtype = fields[i].gettype(); //#6 Object child = fields[i].get(source); //#6 //#6 if ( Modifier.isTransient(fields[i].getModifiers()) ){ //#6 child = null; //#6 //#6 felt.addcontent( serializevariable( fieldtype, child, //#6 target, table)); //#6 //#6 oelt.addcontent(felt); //#6 #3Pracuje s poli odlišně než se skaláry #4získání netřídních atributů (nonstatic) #5Je-li třeba, dovolí přístup. #6Vytváří nové elementy XML 25

else { Class componenttype = sourceclass.getcomponenttype(); //#7 //#7 int length = Array.getLength(source); //#7 oelt.setattribute( "length", Integer.toString(length) ); //#7 //#7 for (int i=0; i<length; i++) { //#7 oelt.addcontent( serializevariable( componenttype, //#7 Array.get(source,i), //#7 target, //#7 table ) ); //#7 //#7 return target; #7 Přidává komponenty pole 26

Serializacekaždé komponenty 1. Je vytvořen jedinečný identifikátor pro každý serializovaný objekt. Objekt a identifikátor jsou uloženi do referenční tabulky, objektse používá jako klíč. 2. Element XML je vytvořen pro objekt, jeho jméno třídy a identifikátor jsou uloženy jako atributy. 3. Odlišné zpracování polí. 27

Serializaceinstančních proměnných Jak serializaceobjektů, tak polí používá metodu serializevariable() k serializaci hodnoty každé instanční proměnné (datového atributu) nebo prvku pole. 28

private static Element serializevariable( Class fieldtype, Object child, Document target, Map table) throws Exception { if (child == null) { return new Element("null"); else if (!fieldtype.isprimitive()) { Element reference = new Element("reference"); if (table.containskey(child)) { reference.settext(table.get(child).tostring()); else { reference.settext( Integer.toString(table.size()) ); serializehelper(child, target, table); return reference; else { Element value = new Element("value"); value.settext(child.tostring()); return value; Metoda prověřuje obsah proměnných a rozhoduje jak je uložit. Primitivní typy vytváří hodnotu elementu obsahujícího Stringverzi primitivního typu. Je-li objekt, jenž již mohl být serializován, je prověřena tabulka identifikátorů. 29

public class Animal { private String name; private String gender; private String classification; private int weight; public Animal(String name, String gender, String classification, int weight) { this.name = name; this.gender = gender; this.classification = classification; this.weight = weight; public String tostring() { return String.format("Animal name %s gender %s classification %s" + " weight %d", name, gender, classification, weight); 30

import java.util.*; public class Zoo extends LinkedList{ private String city; private String name; public Zoo(String city, String name) { this.city = city; this.name = name; public String tostring() { return String.format("Zoo city %s name %s", city, name); 31

public class ZooTest { public static void main( String[] args ) { Animal panda1 = new Animal( "Tian Tian", "male", "Ailuropoda melanoleuca", 271 ); Animal panda2 = new Animal( "Mei Xiang", "female", "Ailuropoda melanoleuca", 221 ); Zoo national = new Zoo( "National Zoological Park", "Washington, D.C." ); national.add( panda1 ); national.add( panda2 ); try { Format format = Format.getPrettyFormat(); // format.setencoding(encoding); XMLOutputter out = new XMLOutputter(format); Document d = Driver.serializeObject( national ); out.output(d, System.out); catch (Exception ex) { ex.printstacktrace(); 32

<?xml version="1.0" encoding="utf-8"?> <serialized> <object class="serialization.zoo" id="0"> <field name="city" declaringclass="serialization.zoo"> <reference>1</reference> </field> <field name="name" declaringclass="serialization.zoo"> <reference>3</reference> </field> <field name="size" declaringclass="java.util.linkedlist"> <null /> </field> <field name="first" declaringclass="java.util.linkedlist"> <null /> </field> <field name="last" declaringclass="java.util.linkedlist"> <null /> </field> <field name="modcount" declaringclass="java.util.abstractlist"> <null /> </field> </object> <object class="java.lang.string" id="1"> <field name="value" declaringclass="java.lang.string"> <reference>2</reference> </field> 33

<field name="hash" declaringclass="java.lang.string"> <value>0</value> </field> <field name="hash32" declaringclass="java.lang.string"> <null /> </field> </object> <object class="[c" id="2" length="24"> <value>n</value> <value>a</value> <value>t</value> <value>i</value> <value>o</value> <value>n</value> <value>a</value> <value>l</value> <value /> <value>z</value> <value>o</value> <value>o</value> <value>l</value> <value>o</value> <value>g</value> <value>i</value> <value>c</value> <value>a</value> <value>l</value> <value /> <value>p</value> <value>a</value> <value>r</value> <value>k</value> 34

</object> <object class="java.lang.string" id="3"> <field name="value" declaringclass="java.lang.string"> <reference>4</reference> </field> <field name="hash" declaringclass="java.lang.string"> <value>0</value> </field> <field name="hash32" declaringclass="java.lang.string"> <null /> </field> </object> <object class="[c" id="4" length="16"> <value>w</value> <value>a</value> <value>s</value> <value>h</value> <value>i</value> <value>n</value> <value>g</value> <value>t</value> <value>o</value> <value>n</value> <value>,</value> <value /> <value>d</value> <value>.</value> <value>c</value> <value>.</value> </object> </serialized> 35

Dynamické nahrávání a reflektivní konstrukce Nahrávání tříd za běhu programu. Vytváření instancí objektů s použitím reflexe. Rozšíření delegování s použitím reflexe. 36

Úvod Web servery jsou klasickým příkladem rozšiřování aplikace za běhu. Servletyjsou třídy, které definují rozšiřující chování, jak mají web servery zacházet s požadavky HTTP. Dynamicky linkované knihovny nutí pracovat mimo programovací jazyk, protože jsou primitivamioperačního systému. 37

Problém k řešení Existuje DBzákazníků, kterou je třeba se dotazovat, pro získání informací. Existuje schéma DB, ale nejsou peníze na replikaci klientského prostředí. Navíc je třeba zevšeobecnit tuto aplikaci pro potenciální prodej jiným klientům. 38

Návrh s využitím vzorů Je třeba využít vzory a delegování pro zvýšení flexibility. Delegováníje opatření, kdy jeden objekt závisí na jiném objektu kvůli implementaci jiného chování. Facade(Fasáda) poskytuje jednotné rozhraní pro množinu jiných rozhraní. Vzor se využívá na dotazy v DB. 39

Návrh s využitím vzorů Tovární metoda poskytuje metodu pro vytváření objektů bez specifikace konkrétních tříd. Tato metoda je volána ke konstrukci implementace fasády. Návrh umožňuje vybrat odpovídající Fasádu beze změny zbytku aplikace 40

MainApplication createdbfacade() : CustomerDatabase StubImpl constructs «interface» CustomerDatabase FileSystemImpl DeploymentImpl Tovární metoda, createdbfacade(), rozhodne, která implementace z CustomerDatabasese bude vytvářet za běhu programu. Rozhraní Fasády, CustomerDatabaseje implementovaná pomocí StubImpl. FileSystemImpl testování DB 41

Návrh s využitím vzorů Tovární metoda, createdbfacade(), vytváří požadovanou implementaci CustomerDatabase pro použití v aplikaci. Není možné vytvořit celou aplikaci před jejím rozmístěním (deploymentem). Nutnost využití reflexe. 42

public class MainApplication { //... private Properties props; private CustomerDatabase custdb; //... public synchronized CustomerDatabase createdbfacade() { if ( custdb == null ) { try { String dbclassname = props.getproperty( "db.class", "com.mcli.app.stubcustomerdb"); Class cls = Class.forName(dbClassName); custdb = (CustomerDatabase) cls.newinstance(); catch (ClassNotFoundException ex) { //... catch (InstantiationException ex) { //... catch (IllegalAccessException ex) { //... return custdb; Klíčové je implementace tovární metody. props odkazuje na java.util.properties použití pro nahrání konfiguračních řetězců do systému, Jedním z konfiguračních vstupů je klíč db.classa jeho hodnota. Hodnota db.classje plně kvalifikovaná jménem třídy, která je využita pro identifikaci třídy fasády konkrétní databáze. Kdokoli se vstupem do souboru propertiesmůže změnit property a takto určit, kterou fasádu databáze aplikace použije. 43

Reflektivní řešení Tovární metoda používá dynamické nahrávání k získání objektu třídy (classobjektu) s klíčem propertydb.class. Dynamickéloadováníje proces ve kterém JVM vytvoří třídy z bytecodu za běhu. Class cls = Class.forName(dbClassName); Získáse objekttřídy, na který odkazuje dbclassname. 44

RozšířeníTovárnímetodyreflexí Vytvoření nové instance: custdb = (CustomerDatabase) cls.newinstance(); Vložením souboru classdo classpatha změnou textu v souboru property. Instalace nové Fasády je snazší, i když již byl systém zaveden (deployed). Pokud se všechny komponenty odkazují na Fasádu prostřednictvím Tovární metody, aplikace může snadno změnit Fasádu. 45

RozšířeníTovárnímetodyreflexí Delegování je užitečné protože dovoluje objektu měnit chování za běhu. Tato změna chování nastane, když jeden delegát poskytuje dané chování je nahrazen jiným s odlišným chováním. Bez mechanismu reflexe je počet delegování omezen na množinu tříd, které jsou začleněny do systému v době kompilace. 46

Nahrávání tříd dynamicky Class cls = Class.forName(dbClassName); Příkaz dovoluje, aby třída, která se používá pro fasádu customerdatabáze byla změněna bez přepisování a rebuildovánízdrojového kódu aplikace. Vrátí se objekt třídy (class object). Class loader(využívá se) již může loadovat třídu. Pokud ano, vrací classobjectkterý loadoval. 47

Nahrávání tříd dynamicky Nebyla-li třída loadovaná, class loader prohledává podle classpathodpovídající soubor.class. Nenajde-li ClassNotFoundException. 48

Reflektivní konstrukce objektů Metoda newinstance() funguje jako bezparametrický konstruktor. Přetypování, které je uvedeno využívat rozhraní místo konkrétních tříd. 49

Použití konstruktoru java.lang.refelction.constructor metatřída konstruktorů. cls.getconstructor(new Class[] { String.class, String.class ) 50

MetodyClasspro introspekci Metoda Constructor getconstructor( Class[] parametertypes) Constructor getdeclaredconstructor( Class[] parametertypes) Constructor[] getconstructors() (sebepozorování) Popis Vrací public konstruktor, se specifikovaným argumentem,pokud ho příjemce metody podporuje. Vrací konstruktor se specifikovaným typem argumentů, pokud ho příjemce metody podporuje. Vrací pole obsahujícím public konstruktory podporované příjemcem. Constructor[] getdeclaredconstructors() Vrací pole obsahujícím konstruktory podporované příjemcem. 51

Návrh pro dynamické loadování Vzniká problém výběru konstruktorů, které budou dynamicky nahrávány (loadovány). Existuje řada rozhraní a řada implementací. Doporučení: implementovat pouze standardní (defaultní) konstruktor a použít instanční metodu pro inicializaci objektu (jeho datových atributů). 52

public interface Parrot { // the rest of the Parrot interface below //... import java.lang.reflect.*; public class ParrotUser { static public void main( String[] args ) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Class parrotclass = Class.forName( "ParrotImpl1" ); Constructor pc = parrotclass.getconstructor( new Class[]{ String.class ); Parrot polly = (Parrot)pc.newInstance( new String[]{ "Polly" ); // Parrot object may now be used Reflektivní konstrukce s argumenty. Přístup preferovaný Javou. 5 deklarovaných výjimek Dohoda mezi programátory, který konstruktor použít. 53

public interface Parrot { void initialize( String name ); // the rest of the Parrot interface below //... public class ParrotUser { static public void main( String[] args ) throws ClassNotFoundException, InstantiationException, IllegalAccessException{ Class parrotclass = Class.forName( "ParrotImpl1" ); Parrot polly = (Parrot)parrotClass.newInstance(); polly.initialize( "Polly" ); // Parrot object may now be used Reflektivní konstrukce s defaultním konstruktorem. initialize() eliminuje chyby programátorů při použití konstruktorů, je děděna do podtříd, každé třídě stačí pouze defaultní konstruktor. 54

Implementace deserializace Deserializace inverzní proces k serializaci (konverze streamu do struktury objektů). Nejdříve musíme vytvořit třídu objektu. Třídu objektu jsme uložili jako plně kvalifikovaný objekt: <object class="serialization.zoo" id="0"> Balíček serialization použijeme: Class.forName pro získání třídy objektu. 55

Implementace deserializace Dále vytvoříme instanci od třídy objektu (newinstance() to udělá bez). Musíme doplnit hodnotu datových atributů. Primitivní typy. Objektové typy nejdříve vytvořit instanci rekurzivní proces. 56

public static Object deserializeobject( Document source ) throws Exception { List objlist = source.getrootelement().getchildren(); Map table = new HashMap(); createinstances( table, objlist ); assignfieldvalues( table, objlist ); return table.get("0"); Inicializace deserializace Nejdříve získá seznam dětí z dokumentu XML. Každý element z dokumentu reprezentuje nějaký objekt. HashMapse použije k mapování identifikátorů na deserializované objekty. Během serializacedostal každý objekt jednotný identifikátor ten je klíčem. createinstance() load třídy, instance konstruktorů a mapuje je k jejich identifikátorům. 57

private static void createinstances( Map table, List objlist ) throws Exception { for (int i = 0; i < objlist.size(); i++) { Element oelt = (Element) objlist.get(i); Class cls = Class.forName(oElt.getAttributeValue("class")); //#1 Object instance = null; if (!cls.isarray()) { Constructor c = cls.getdeclaredconstructor(null); if (!Modifier.isPublic(c.getModifiers())) { c.setaccessible(true); instance = c.newinstance(null); else { instance = Array.newInstance( cls.getcomponenttype(), Integer.parseInt(oElt.getAttributeValue("length"))); table.put(oelt.getattributevalue("id"), instance); Konstrukce instancí: iterace seznamem serializovanýchobjektů XML dokumentu. #1 dotaz dokumentu na jméno třídy serializovanéhoobjektu a nahrání (load) této třídy.

private static void assignfieldvalues( Map table, List objlist ) throws Exception { for (int i = 0; i < objlist.size(); i++) { Element oelt = (Element) objlist.get(i); Object instance = table.get( oelt.getattributevalue("id") ); List felts = oelt.getchildren(); if (!instance.getclass().isarray()) { for (int j=0; j<felts.size(); j++) { Element felt = (Element) felts.get(j); String classname = felt.getattributevalue("declaringclass"); Class fielddc = Class.forName(className); String fieldname = felt.getattributevalue("name"); Field f = fielddc.getdeclaredfield(fieldname); if (!Modifier.isPublic(f.getModifiers())) { f.setaccessible(true); Obnovení struktury objektů: 1/2 Element velt = (Element) felt.getchildren().get(0); f.set( instance, deserializevalue( velt, f.gettype(), table ) ); 59

else { Class comptype = instance.getclass().getcomponenttype(); for ( int j = 0; j < felts.size(); j++) { Array.set( instance, j, deserializevalue( (Element)fElts.get(j), comptype, table )); Obnovení struktury objektů: 2/2 60

private static Object deserializevalue( Element velt, Class fieldtype, Map table ) throws ClassNotFoundException { String valtype = velt.getname(); if (valtype.equals("null")) { return null; else if (valtype.equals("reference")) { return table.get(velt.gettext()); else { if (fieldtype.equals(boolean.class)) { if (velt.gettext().equals("true")) { return Boolean.TRUE; else { return Boolean.FALSE; Deserializace metod: 1/2 61

else if (fieldtype.equals(byte.class)) { return Byte.valueOf(vElt.getText()); else if (fieldtype.equals(short.class)) { return Short.valueOf(vElt.getText()); else if (fieldtype.equals(int.class)) { return Integer.valueOf(vElt.getText()); else if (fieldtype.equals(long.class)) { return Long.valueOf(vElt.getText()); else if (fieldtype.equals(float.class)) { return Float.valueOf(vElt.getText()); else if (fieldtype.equals(double.class)) { return Double.valueOf(vElt.getText()); else if (fieldtype.equals(char.class)) { return new Character(vElt.getText().charAt(0)); else { return velt.gettext(); Deserializace metod: 2/2 62

Závěr Skutečná flexibilita vyžaduje, aby aplikace byly schopné začlenit nový kód. Dynamické loadování dovoluje javovské aplikaci nalézt a použít třídy, které nebyly dostupné při psaní aplikace. Dynamické loadovánívytváří objekty třídy (class objects). Instanciovánítěchto objektů tříd je nezbytnou podmínkou. 63