Egy másik késztetés az osztályinformációk kiderítésére futásidõben képességet ad létrehozni és végrehajtani objektumokat távoli platformon a hálózaton keresztül. Ezt hívják távoli metódus hívásnak(RMI) és ez  biztosítja egy Java programnak az objektumoknak a kiosztását számítógépeken keresztül. Ez a disztribució történhet számos okból: például, amikor csinálsz egy intenzív számítási feladatot és részekre akarod tördelni, és darabokat adni egy számítógépnek - amely kihasználatlan - a sebesség növelése céljából. Néhány szituációban helyet kell foglalnod a feladat egyéni típusainak (pl. "Üzleti szabályok",  többszörös kliens/server architekturáknál) speciális gépeken, így ez a számítógép egy közös tár lesz, és leírja a tevékenységeket, és ezt bárki a rendszerből könnyedén befolyásolhatja. (Ez egy érdekes fejlesztés mióta a számítógép létezik, a szoftverfejlesztés közben egyszerűen módosíthatjuk a programot. Tovább ezen az úton, az osztott számitás speciális hardvert követel ami jó a részfeladatokhoz- például: Matrix inveziójának előállításához- de alkalmatlan illetve túl drága általános célú programozáshoz.

A Class osztály (Az előző fejezetben leirt) támogatja a tükrözés koncepcióját, és ez egy kiegészítő könyvtár, java.lang.reflect, osztályok Mezőivel, Metódussal és Konstructorral (ezek implementálva vannak a Member Interface-ben). Ezeknek az objektumoknak a típusait a JVM hozza létre futási időben, hogy egyeztesse a megfelelő tagokat a névtelen osztályban. Ezután használhatóak a Konstruktorok új objektum létrehozásánál, a get() és set() metódusokat, hogy olvassuk, illetve modosítsuk azokat a mezőket, amelyek társítva vannak a Field objektummal, és az Invoke() metódust, hogy hívjunk egy metódust, amely társítva van egy Method objektummal. Ráadásul, hívhatod a megfelelő metódusokat a getFields(), getMethods(), getConstructors() -al stb. és a visszatérési érték egy tömb lesz, melyben az objektumok mezői, metódusai és konstrutorai. (Többet is megtudhatsz ha utánanézel a Class osztálynak a JDK dokumentációban.) Az ismeretlen objektumok osztály információi egyértelműen meghatározottak futási időben és semmit nem szükséges tudni róla fordításnál.

Fontos, hogy rájőjjünk, semmi mágikus nincs a tükröződésben. Ha használod a tükröződést egy névtelen típus egy objektuma egymásra hat, a JVM egyszerűen megnézi az objektumot és látja, hogy tartozik hozzá egy osztály (pont mint a megszokott RTTI-nél) de ezután miután történne bármi más a Class objektum betöltődik. Így a .class fiájl, mint egy egyéni típus még elérhetővé válik a JVM számára, a helyi gépen vagy a hálózaton keresztül. Tehát az igazi különbség az RTTI és tükröződés között: RTTI-el a fordító megnyitja és megvizsgálja a .class fájl fordításkor. Egy másik mód, meg kell hívnod az objektum összes metódusát a "normális" úton. Tükröződéssel, a .class fájl elérhetetlen fordításkor; a futási környezet nyitja meg és ellenőrzi ezt.

Az osztály metódus kifejtő


Szüség lehet időközönként a reflection eszközök közvetlen használatára; ezek egy nyelvben vannak, hogy támogassák más Java jelleget is úgy mint objektum sorozatát (12. fejezet) és JavaBeans (14. fejezet). Van amikor ez egészen hasznos, hogy dinamikusan is elő tud állni az információ egy osztályról. Egy módfelett hasznos eszköz az osztály metódus kifejtő. Ahogy az előbb említettük, megnézi az osztály definíció forrás kódot vagy JDK dokumentációt és csak a metódusokat mutatja, amelyek defináltak vagy túlterheltek, azok osztály definícióik nélkül. De lehet egy tucatnál is több elérhető számodra, melyek még az alaposztályokból jönnek. Ezeknek a megállapítása fáradságos és időrabló¹. Szerencsére, reflection gondoskodik az írásról egyszerűen, ami automatikusan meg fogja mutatni a teljes interface-t. Itt egy példa a használatára:

¹ Főleg a múltban. Sun nagyban javítja a HTML Java dokumentációt , így ennek segítségével könnyebb látni az alap osztály metódusokat.
//: c10:ShowMethods.java
// Reflekció használata, hogy megnutassuk az összes metódusát az osztálynak,
// még ha azok az alap osztályban vannak definiálva is.
// {Args: ShowMethods}
import java.lang.reflect.*;
import java.util.regex.*;
 
public class ShowMethods {
  private static final String usage =
    "usage: \n" +
    "ShowMethods pified.class.name\n" +
    "To show all methods in class or: \n" +
    "ShowMethods pified.class.name word\n" +
    "To search for methods involving 'word'";
  private static Pattern p = Pattern.compile("\\w+\\.");
public static void main(String[] args) {
  if(args.length < 1) {
    System.out.println(usage);
    System.exit(0);
  }
  int lines = 0;
  try {
    Class c = Class.forName(args[0]);
    Method[] m = c.getMethods();
    Constructor[] ctor = c.getConstructors();
    if(args.length == 1) {
      for(int i = 0; i < m.length; i++)
      System.out.println(
        p.matcher(m[i].toString()).replaceAll(""));
    for(int i = 0; i < ctor.length; i++)
      System.out.println(
        p.matcher(ctor[i].toString()).replaceAll(""));
    lines = m.length + ctor.length;
  } else {
    for(int i = 0; i < m.length; i++)
      if(m[i].toString().indexOf(args[1]) != -1) {
        System.out.println(
          p.matcher(m[i].toString()).replaceAll(""));
        lines++;
    }
  for(int i = 0; i < ctor.length; i++)
    if(ctor[i].toString().indexOf(args[1]) != -1) {
      System.out.println(p.matcher(
        ctor[i].toString()).replaceAll(""));
      lines++;
    }
  }
} catch(ClassNotFoundException e) {
System.out.println("No such class: " + e);
}
}
} ///:~

A Class metódusok getMethod() és getConstructors() egy Metódus tömbbel és Konstructor tömbbel térnek vissza. Ezeknek az osztályoknak a távolabbi metódusait szétdarabolja a névre, argumentumaira, és visszatér a metódusok értékeivel, amiket feltüntet. De használhatod a toString()-et is ahogyan a példában tették: előállít egy Stringet  a teljes Metódus aláírással. A kód többi részét előállítja a parancs sor információ, megállapítja, ha egy egyéni aláírás illik a cél stringre (használd: indexOf()), és leteszi a név módosítást.

A név darabja a "java.lang.String"-ben van, Java JDK 1.4 szabályos kifejezés kínál egy hatékony és tömör eszközt, amely már elérhető néhány nyelvben sok éve. Láthattad a szabályos kifejezések egyszerű kezelését a com.bruceekel.simple.Test osztály expect() utasításában. A fenti példában, láthattad az alap kódolási lépéseket, szüségszerűen használtunk előírás szerinti kifejezéseket a programjainkban.

A  java.util.regex importálása után, a fordításnál a szabályos kifejezések először a static Pattern.compile() metódust használják, amely létrehozza a Pattern objektumot a string argumentum használatával. Ebben az esetben az argumentum:
"\\w+\\."
Ahhoz, hogy megértsük ezt vagy más reguláris kifejezést meg kell néznünk a JDK dokumentációt a java.util.regex.Pattern című résznél. az egyikben a '\w' szerepelt, melynek jelentése "egy szó karakter: [a-zA-Z_0-9]." a '+' jelentése " egy vagy több megelőző kifejezés" - igy ebben az esetben, egy vagy több szó karakterek - és a '\' létrehoz egy literális periódust (inkább mint a periódus operátor meynek jelentése "bármely karakter" a reguláris kifejezésből). Így ez a kifejezés fogja összekötni a szó karakterek egymást követő tagjait a periódusban, amely pontosan az amire szükségünk van a módosítások rögzítéséhez.

Ezek után van neked egy lefordított Pattern objektumod, használhatod a matcher() metódus hívására, átadni a stringet amit keresni akarunk. A matcher() metódus készít egy Matcher objektumot, melynek van egy halmaz operációja, melyeket kiválaszthatod (az összeset láthatod a JDK dokumentációban: java.util.regex.Mather). Itt a replaceAll() metódus arra használatos, hogy felcserlje az összes match-et üres stringre- lényegében törli a match-eket. Egy még tömörebb alternativa, ha használod a reguláris kifejezéseket, azokkal elkészítheted a String osztályt. Például az előbb használt replaceAll() a fenti programban akár a következőket át is lehetett volna írni erről:
p.matcher(ctor[i].toString()).replaceAll("")
erre:
ctor[i].toString().replaceAll("\\w+\\.", "")
előfordítás nélkül a reguláris kifejezés. Ez a forma jó az egyszerhasználatos reguláris kifejezéseknél, de az előfordított forma jelentősen hatékonyabb ha szükséged van a reguláris kifejezés többszörös használatára, ebben az esetben jó ez a példa.

Ez a példa megmutatja a reflekciót működés közben, amióta az eredményt a Class.forName() produkálja, nem tudhatjuk fordításkor azt, és következésképpen az összes metódus információ futási időben fejtődik ki. Ha tanulmányozod a JDK dokumentációt a reflekcóról akkor látni fogod:  van elég támogatás, hogy valóban csináljon egy wgy metódus hívást egy objektumon ami teljesen névtelen fordításkor (erre lesz példa a későbbiekben a könyben). Bár kezdetben ez olyasmi, amiről nem is gondolnád, hogy valaha is szükséged lesz rá, ám a teljes reflekció értéke egészen meglepő.

Egy rávilágító próba futtatni:
java ShowMethods ShowMethods
Ez produkál egy listát ami magába foglalja a publikus alapértelmezett konstruktorokat, még a kódokat is láthatod, melyeket nem a konstruktorok definiáltak. A konstruktor az egyik amit a fordító automatikusan szintetizál. Ha ezután  csinálsz ShowMethods -ot egy nem publikus osztályon (ez csomag hazzáférhető), a hozzáadott alaértelmezett konstruktor nem mutat távolabbra a kimenetben. A hozzáadott alaértelmezett konstruktor  automatikusan ugyanazt a hozzáférhetőséget adja, mint az osztálynak.

Másik érdekes tapasztalat, hogy a java ShowMethods segítségül hívja a java.lang.String-et char, int, String, stb. extra argumentumokkal. Ez az eszköz időmegtakarító tud lenni, miközben programozol, amikor nem emlékszel egy osztélynak az egyéni metódusára és nem akarsz keresgélni az indexek vagy az osztály hierarchia között a JDK dokumentációban vagy ha nem tudod melyik osztállyal miket lehet csinálni. Például: Color (szín) objektumok.

A 14. fejezet tartalmazza ennek a programnak a GUI (felhasználói felület) verzióját (testreszabható az információ kifejtése a rugalmas komponenseknél) így el is hagyható futáskor, miközben írod a kódot, a gyorskeresés engedélyezve van.

Összegzés

RTTI megengedi neked, hogy kiderítsd a típus információkat ismeretlen osztály hivatkozásokról. Ez elég összetett, hogy a kezdők rosszul kezeljék, ezt kell elsajátítani mielőtt polimorf metódusokat hívnánk. Sok ember procedurális háttérrel jön, nem olyan bonyolult megszervezni az ő programjaikat a switch utasítás halmazaival. Elvégezhetik ezt az RTTI-vel és így elveszthetik a polimorfizmus fontos változóit a program fejlesztésénél és a karbantartás. A Java szándéka, hogy használjuk a polimorf metódus hívásokat a kódon belül, és az RTTI-t csak akkor használjuk, amikor muszály.

Azonban, a polimorf metódus hívások használata megköveteli, hogy az alap-osztály definíciókat ellenörzés alatt tartsuk, mert néhány helyen meghosszabbíthatja a programod, fel kell fedezned azt, hogy az alap osztályok nem foglalják magukba a metódust, amelyre szüséged van. Ha az alap osztály egy könyvtárban található vagy másvalaki tarja irányítás alatt, akkor egy megoldás a problémára az  RTTI: örökölhetsz egy új típust és hoozáadhatod az extra metódusodat. Máskülönben a kódban megállapíthatod a helyét az egyéni típusodnak és egy speciális metódus segítségével meghívhatod. Ez nem semmisíti meg a program polimorfizmusát és kiterjeszthetőségét, mert új típus hozzáadása nem fog megkövetelni keresést az összekötött utasításokra a programodban. Azonban, amikor hozzáadsz új kódot a főrészhez, az megkövetel új tulajdonságot, Az RTTI-t kell használnod, hogy megállapítsd az egyéni típusod.

A tulajdonságok elhelyezése az alap osztályokban egy egyéni osztály előnyére válhat, az összes más osztályok származtathatók az alap követelmény néhány semmitmondó metódus csonkból. Ezt az interface csinálja, kevésbé vlágos és bosszantó ha ezek túlterhelt absztrakt metódusok és az alap osztályból lettek származtatva. Például: tekintsünk egy osztály hierarchiát a hangszerek bemutatásával. Meg kell tisztítani a hangszereket a zenekarban. Egy választás ha beteszed a clearSpitValve() metódust az alap osztályban, amely az Instrument (hangszerek), de ez zavaró, mert magába foglalja az ütős -és Elektronikus hangszereket szintén van fúvókája. RTTI nyújt  sokkal ésszerűbb bontást ebben az esetben, mert lehet hely egy metódus számára a különleges osztályban (FúvósHangszerek ebben az esetben), itt ez helyénvaló. Azonban egy még helyénvalóbb bontás is elképzelhető, ha a prepareInstrument() metódust beletesszük az alap osztályba, de nem láthattad, amikor először próbáltad megoldani a problémát, és lehet, hogy tévesen használtad volna az RTTI-t.