



<html>
<head>
  <title>javabog.dk -  - Introspektion</title>
  <link rev="stylesheet" type="text/css" href="../typografi.css">
  <meta name="description" content="Lærebog i Java. Af Jacob Nordfalk. Udkommet hos Forlaget Globe">
  <meta name="keywords" content="designmønster, programmering, OOP, objekter, klasser, objektorienteret programmering, Java, JSP, lærebog, UML, IT">
</head>
<body bgcolor="#ffffff">



<a href='http://javabog.dk/'>javabog.dk</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel10.jsp'>&lt;&lt; forrige</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='indhold.jsp'>indhold</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel12.jsp'>n&aelig;ste &gt;&gt;</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kode/'>programeksempler</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='../index_VP.html'>om bogen</a>

<H1 CLASS="western" STYLE="">11 <a name='afsn11'></a>Introspektion</H1>
<DIV ID="Indholdsfortegnelse14">
  <P STYLE="margin-top: 0.3cm; margin-bottom: 0cm"><BR>
  </P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>11.1
  L&aelig;se klasseinformation for et objekt  152</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">11.1.1
  Oversigt over pakken java.lang.reflect  152</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">11.1.2
  Opremse metoderne i en klasse  153</FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>11.2
  Arbejde med objekter  153</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>11.3
  Introspektion p&aring; javab&oslash;nner  154</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>11.4
  Generere nye klasser og indl&aelig;se dem  155</B></FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">11.4.1
  Kalde overs&aelig;tteren som eksternt program  155</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">11.4.2
  Bruge overs&aelig;tteren internt  155</FONT></FONT></P>
  <P STYLE="margin-left: 0.6cm; margin-top: 0.08cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 9pt">11.4.3
  Indl&aelig;se klasser fra filsystemet  156</FONT></FONT></P>
  <P STYLE="margin-left: 0.3cm; margin-top: 0.15cm; margin-bottom: 0cm">
  <FONT FACE="Helvetica, sans-serif"><FONT SIZE=2 STYLE="font-size: 11pt"><B>11.5
  Videre l&aelig;sning  157</B></FONT></FONT></P>
</DIV>

<P CLASS="western" STYLE="">Introspektion
(eng.: Introspection eller reflection) handler om, hvordan man under
k&oslash;rslen af programmet kan inspicere et <I>vilk&aring;rligt
objekt</I>, finde dets klasse, finde ud af, hvilke metoder og
variabler klassen har, kalde metoderne og afl&aelig;se/s&aelig;tte
variablerne, oprette nye objekter fra klassen etc. etc.</P>
<P CLASS="western">Introspektion bruges sj&aelig;ldent i almindelige
programmer, men det kan v&aelig;re nyttigt at kende til mulighederne
for introspektion for at forst&aring;, hvordan andre programmer,
bl.a. udviklingsv&aelig;rkt&oslash;j, fungerer.</P>
<H2 CLASS="western">11.1 <a name='afsn11.1'></a>L&aelig;se klasseinformation for et objekt</SPAN></H2>
<P CLASS="western">Stamklassen java.lang.Object, som alle objekter
direkte eller indirekte arver fra, indeholder metoden getClass() - og
ethvert objekt har derfor getClass(). Denne metode returnerer en
repr&aelig;sentation af objektets <I>klasse</I> (af typen
java.lang.Class).</P>
<P CLASS="western">I eksemplet herunder opretter vi et Frame-objekt
og henter dets klasse. Vi kigger derefter p&aring; superklasserne og
udskriver dem.</P>
<PRE CLASS="kode-western">import java.lang.reflect.*;
<SPAN LANG="da-DK">import java.awt.*;</SPAN>

<SPAN LANG="da-DK">public class UndersoegKlasse</SPAN>
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  public static void main(String[] args)</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    Object o = new Frame();</SPAN>

<SPAN LANG="da-DK">    // Find klassen</SPAN>
<SPAN LANG="da-DK"><B>    Class klasse = o.getClass();</B></SPAN>
<SPAN LANG="da-DK">    System.out.println(&quot;Klassen navn er: &quot;+<B>klasse.getName()</B>);</SPAN>

<SPAN LANG="da-DK">    // Find superklasserne</SPAN>
<SPAN LANG="da-DK">    Class <B>superklasse = klasse.getSuperclass()</B>;</SPAN>
<SPAN LANG="da-DK">    while (superklasse != null)</SPAN>
<SPAN LANG="da-DK">    {</SPAN>
<SPAN LANG="da-DK">      System.out.println(&quot;... og den har superklasse: &quot;+<B>superklasse.getName()</B>);</SPAN>
<SPAN LANG="da-DK">      superklasse = superklasse.getSuperclass();</SPAN>
<SPAN LANG="da-DK">    }</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE>
<HR>
<PRE CLASS="kode-western">Klassen navn er: java.awt.Frame
<SPAN LANG="da-DK">... og den har superklasse: java.awt.Container</SPAN>
<SPAN LANG="da-DK">... og den har superklasse: java.awt.Component</SPAN>
<SPAN LANG="da-DK">... og den har superklasse: java.lang.Object</SPAN></PRE><P CLASS="western">
Man ser, at Frame er en Container, der igen arver fra Component, som
arver fra Object.</P>
<H3 CLASS="western">11.1.1 <a name='afsn11.1.1'></a>Oversigt over pakken java.lang.reflect</H3>
<P CLASS="western">Class-objekter har metoder til at sp&oslash;rge om
alt, hvad der er v&aelig;rd at vide om klassen, herunder  variabler,
konstrukt&oslash;rer og metoder (der bruges hj&aelig;lpeklasserne
Field, Constructor og Method). De vigtigste er opremset herunder:</P>
<P ALIGN=CENTER STYLE="margin-top: 0.21cm; margin-bottom: 0cm"><FONT SIZE=2 STYLE="font-size: 9pt"><I>Vigtigste
metoder i Class (der repr&aelig;senterer en klasse)</I></FONT></P>
<P CLASS="klasseoversigt---kompakt-western">String getName()    giver
en streng med klassens navn (og pakkenavn)</P>
<P CLASS="klasseoversigt---kompakt-western">Class
getSuperclass()  giver Class-objektet, der repr&aelig;senterer
superklassen</P>
<P CLASS="klasseoversigt---kompakt-western">Class[]
getInterfaces()  giver et array med de interfaces, klassen
implementerer</P>
<P CLASS="klasseoversigt---kompakt-western">Field[]
getFields()    giver et array med de variabler, der er erkl&aelig;ret
public i klassen</P>
<P CLASS="klasseoversigt---kompakt-western">Constructor[]
getConstructors() giver et array med de konstrukt&oslash;rer, der er
erkl&aelig;ret public</P>
<P CLASS="klasseoversigt---kompakt-western">Method[]
getMethods()  giver et array med de metoder, der er erkl&aelig;ret
public i klassen</P>
<P CLASS="klasseoversigt---kompakt-western">Class[]
getClasses()    giver et array af de indre klasser (og interfaces), der
er public i klassen</P>
<P CLASS="western">Ved normal introspektion af en klasse ses kun
variabler, metoder og konstrukt&oslash;rer, der er erkl&aelig;ret
public. Vil man ogs&aring; se protected, pakke og private
variabler/metoder/konstrukt&oslash;rer p&aring; klassen skal man
bruge nogle tilsvarende metoder, der starter med <I>getDeclared</I>,
f.eks. getDeclaredFields(), getDeclaredConstructors() og
getDeclaredMethods(). Disse metoder giver alle data, men der sker
f&oslash;rst et sikkerhedstjek for, om den kaldende tr&aring;d har
tilladelse til at f&aring; disse oplysninger (det har f.eks. en
applet ikke).</P>
<H3 CLASS="western">11.1.2 <a name='afsn11.1.2'></a>Opremse metoderne i en klasse</H3>
<P CLASS="western">I eksemplet herunder f&aring;r vi med getMethods()
et array af alle metoder i klassen, der er erkl&aelig;ret public.
Dette genneml&oslash;bes, og for hver metode udskrives retur- og
parametertyper. 
</P>
<PRE CLASS="kode-western">import java.lang.reflect.*;
<SPAN LANG="da-DK">import java.awt.*;</SPAN>

<SPAN LANG="da-DK">public class FindMetoder</SPAN>
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  public static void main(String[] args)</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    Object o = new Button();</SPAN>

<SPAN LANG="da-DK">    // Find klassen</SPAN>
<SPAN LANG="da-DK">    Class klasse = o.getClass();</SPAN>
<SPAN LANG="da-DK">    System.out.println(&quot;Klassen navn er: &quot;+klasse.getName());</SPAN>

<SPAN LANG="da-DK">    Method[] metoder = <B>klasse.getMethods()</B>;</SPAN>
<SPAN LANG="da-DK">    for (int i=0; i&lt;metoder.length; i++)</SPAN>
<SPAN LANG="da-DK">    {</SPAN>
<SPAN LANG="da-DK">      Method m = metoder[i];</SPAN>
<SPAN LANG="da-DK"><B>  </B>    System.out.print(&quot;Metode &quot;+<B>m.getName()</B>);</SPAN>
<SPAN LANG="da-DK"><B>  </B>    System.out.print(&quot; har returtype: &quot;+<B>m.getReturnType().getName()</B>);</SPAN>
<SPAN LANG="da-DK">      Class[] <B>parametertyper = m.getParameterTypes()</B>;</SPAN>
<SPAN LANG="da-DK">      System.out.print(&quot; og parametertyper:&quot;);</SPAN>
<SPAN LANG="da-DK">      for (int j=0; j&lt;parametertyper.length; j++)</SPAN>
<SPAN LANG="da-DK">        System.out.print(&quot; &quot; + <B>parametertyper[j].getName()</B>);</SPAN>
<SPAN LANG="da-DK">    }</SPAN>
<SPAN LANG="da-DK">    System.out.println();</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE>
<HR>
<PRE CLASS="kode-western">Klassen navn er: java.awt.Button
<SPAN LANG="da-DK">...</SPAN>
<SPAN LANG="da-DK">Metode: notify har returtype: void</SPAN>
<SPAN LANG="da-DK">Metode: notifyAll har returtype: void</SPAN>
<SPAN LANG="da-DK">Metode: toString har returtype: java.lang.String</SPAN>
<SPAN LANG="da-DK">...</SPAN>
<SPAN LANG="da-DK">Metode: getLabel har returtype: java.lang.String</SPAN>
<SPAN LANG="da-DK">Metode: setLabel har returtype: void og parametertyper: java.lang.String</SPAN>
<SPAN LANG="da-DK">...</SPAN></PRE><P CLASS="western">
Programudskriften er ret lang, idet ogs&aring; superklassernes
metoder udskrives.</P>

<H2 CLASS="western">11.2 <a name='afsn11.2'></a>Arbejde med objekter</SPAN></H2>
<P CLASS="western">Ud over at inspicere klasserne er der ogs&aring;
mulighed for at arbejde aktivt med dem:</P>
<UL>
  <LI><P CLASS="western">Class-objekter har metoden newInstance(), der
  opretter et objekt ved at bruge standardkonstrukt&oslash;ren (er der
  ikke adgang til standardkonstrukt&oslash;ren, kastes en undtagelse).</P>
  <LI><P CLASS="western">&Oslash;nsker man at bruge en anden
  konstrukt&oslash;r, f&aring;r man arrayet af andre konstrukt&oslash;rer
  ved at kalde getConstructors(). Hvert Constructor-objekt har metoden
  newInstance() til at oprette et objekt med netop denne konstrukt&oslash;r.</P>
  <LI><P CLASS="western">Hver Field (variabel) har metoderne get() og
  set() til at arbejde med variablens v&aelig;rdi.</P>
  <LI><P CLASS="western">Hvert Method-objekt har metoden invoke() til
  at kalde metoden p&aring; objektet (der er et eksempel p&aring; brug
  herunder).</P>
</UL>
<H2 CLASS="western">11.3 <a name='afsn11.3'></a>Introspektion p&aring; javab&oslash;nner</SPAN></H2>
<P CLASS="western">Netop til javab&oslash;nner findes der nogle
klasser i pakken java.beans, der er specielt velegnede til at
unders&oslash;ge og manipulere med egenskaber (dvs. get- og
set-metoder, se <a href='kapitel4.jsp'>kapitel 4</a>, Komponentbaseret programmering). 
</P>
<P CLASS="western">Man kan f.eks. opremse en b&oslash;nnes
egenskaber, udskrive en beskrivelse af hver egenskab og afl&aelig;se
dens v&aelig;rdi:</P>
<PRE CLASS="kode-western" STYLE="font-weight: medium">import java.lang.reflect.*;
<SPAN LANG="da-DK">import javax.swing.*;</SPAN>
<SPAN LANG="da-DK">import java.beans.*;</SPAN>

<SPAN LANG="da-DK">public class Boenneintrospektion </SPAN>
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  public static void main(String[] args) throws Exception</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    Object <B>objekt = new JButton()</B>;</SPAN>
<SPAN LANG="da-DK">    Class <B>klasse = objekt.getClass()</B>;</SPAN>
<SPAN LANG="da-DK">    BeanInfo <B>b&oslash;nneinfo = Introspector.getBeanInfo(klasse)</B>;</SPAN>
<SPAN LANG="da-DK">    PropertyDescriptor <B>egenskaber[] = b&oslash;nneinfo.getPropertyDescriptors()</B>;</SPAN>

<SPAN LANG="da-DK">    for (int i=0; i&lt;egenskaber.length; i++)</SPAN>
<SPAN LANG="da-DK">    {</SPAN>
<SPAN LANG="da-DK">      PropertyDescriptor e = egenskaber[i];</SPAN>

<SPAN LANG="da-DK">      System.out.print(e.getName()+&quot;: &quot;+e.getShortDescription());</SPAN>

<SPAN LANG="da-DK">      Method <B>l&aelig;semetode = e.getReadMethod()</B>;</SPAN>
<SPAN LANG="da-DK">      if (l&aelig;semetode != null) </SPAN>
<SPAN LANG="da-DK">      {</SPAN>
<SPAN LANG="da-DK">        Object[] tomParameterliste = {};</SPAN>
<SPAN LANG="da-DK">        Object <B>v&aelig;rdi = l&aelig;semetode.invoke</B>(objekt,tomParameterliste);</SPAN>
<SPAN LANG="da-DK">        System.out.print(&quot; (v&aelig;rdi=&quot;+v&aelig;rdi+&quot;)&quot;);</SPAN>
<SPAN LANG="da-DK">      }</SPAN>

<SPAN LANG="da-DK">      <I>// s&aelig;t egenskaben til true, hvis den kan s&aelig;ttes og er af type boolean</I></SPAN>
<SPAN LANG="da-DK">      Method <B>skrivemetode = e.getWriteMethod()</B>;</SPAN>
<SPAN LANG="da-DK">      if (skrivemetode!=null &amp;&amp; e.getPropertyType()==java.lang.Boolean.TYPE)</SPAN>
<SPAN LANG="da-DK">      {</SPAN>
<SPAN LANG="da-DK">        Boolean[] parameterlisteMedTRUE = { Boolean.TRUE };</SPAN>
<SPAN LANG="da-DK"><SPAN STYLE="font-weight: medium">        </SPAN><B>skrivemetode.invoke</B><SPAN STYLE="font-weight: medium">(objekt, parameterlisteMedTRUE ); <I>// s&aelig;t egenskab</I></SPAN></SPAN>
<SPAN LANG="da-DK">      }</SPAN>
<SPAN LANG="da-DK">      System.out.println();</SPAN>
<SPAN LANG="da-DK">    }</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE><P CLASS="western">
Herunder ses, hvad programmet skriver ud (nogle linjer er fjernet):</P>
<PRE CLASS="kode-western" STYLE="font-weight: medium">icon: The button's default icon (v&aelig;rdi=null)
<SPAN LANG="da-DK">inputMap: inputMap (v&aelig;rdi=javax.swing.InputMap@6e3d60)</SPAN>
<SPAN LANG="da-DK">insets: insets (v&aelig;rdi=java.awt.Insets[top=5,left=17,bottom=5,right=17])</SPAN>
<SPAN LANG="da-DK">alignmentY: The preferred vertical alignment of the component. (v&aelig;rdi=0.5)</SPAN>
<SPAN LANG="da-DK">alignmentX: The preferred horizontal alignment of the component. (v&aelig;rdi=0.0)</SPAN>
<SPAN LANG="da-DK">toolTipText: The text to display in a tool tip. (v&aelig;rdi=null)</SPAN>
<SPAN LANG="da-DK">mnemonic: the keyboard character mnemonic (v&aelig;rdi=0)</SPAN>
<SPAN LANG="da-DK">verticalAlignment: The vertical alignment of the icon and text. (v&aelig;rdi=0)</SPAN>
<SPAN LANG="da-DK">defaultButton: Whether or not this button is the default button (v&aelig;rdi=false)</SPAN>
<SPAN LANG="da-DK">rolloverEnabled: Whether rollover effects should be enabled. (v&aelig;rdi=false)</SPAN>
<SPAN LANG="da-DK">horizontalAlignment: The horizontal alignment of the icon and text. (v&aelig;rdi=0)</SPAN>
<SPAN LANG="da-DK">borderPainted: Whether the border should be painted. (v&aelig;rdi=true)</SPAN></PRE><P CLASS="western">
Metoden <SPAN STYLE="font-weight: medium">getShortDescription()
henter en beskrivelse af egenskaben fra b&oslash;nnens
BeanInfo-klasse (ekstra information, der er beregnet til
udviklingsv&aelig;rkt&oslash;j, se <a href='kapitel4.jsp#afsn4.3.3'>afsnit 4.3.3</a>). K&oslash;rer du
selv eksemplet, kan det v&aelig;re, at den ekstra information ikke er
tilg&aelig;ngelig, og da giver getShortDescription() blot det korte
navn.</SPAN></P>

<H2 CLASS="western">11.4 <a name='afsn11.4'></a>Generere nye klasser og indl&aelig;se dem</SPAN></H2>
<P CLASS="western">Et sp&oslash;rgsm&aring;l relateret til
introspektion er: 
</P>
<UL>
  <LI><P CLASS="western">Hvordan kan et program lave nye klasser og
  indl&aelig;se dem? 
  </P>
  <LI><P CLASS="western">Hvordan kan man overs&aelig;tte en .java-fil
  (kildetekst) til en .class-fil (bytekode)?</P>
</UL>
<H3 CLASS="western">11.4.1 <a name='afsn11.4.1'></a>Kalde overs&aelig;tteren som eksternt
program</H3>
<P CLASS="western">En mulighed for at overs&aelig;tte en .java-fil
til en .class-fil er at kalde overs&aelig;tteren javac som et
eksternt program, ligesom det g&oslash;res fra kommandolinjen,
f.eks.:</P>
<PRE CLASS="kode-western">public class KaldJavacEksternt
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  public static void main(String[] args) throws Exception</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    Runtime r = Runtime.getRuntime();</SPAN>
<SPAN LANG="da-DK">    Process p = r.exec(&quot;javac UndersoegKlasse.java&quot;);</SPAN>
<SPAN LANG="da-DK">    p.waitFor();                               <I>// vent p&aring; at processen er f&aelig;rdig</I></SPAN>
<SPAN LANG="da-DK">    System.out.println(&quot;f&aelig;rdig&quot;);</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE>
<HR>
<PRE CLASS="kode-western">f&aelig;rdig</PRE><P CLASS="western">
Man skal v&aelig;re opm&aelig;rksom p&aring;, at kommandoen 'javac'
skal v&aelig;re tilg&aelig;ngelig fra kommandolinjen. Det kan f.eks.
ske ved at &aelig;ndre i stien (PATH-milj&oslash;variablen).</P>
<H3 CLASS="western">11.4.2 <a name='afsn11.4.2'></a>Bruge overs&aelig;tteren internt</H3>
<P CLASS="western">Overs&aelig;tteren er faktisk programmeret i Java
og findes i klassen com.sun.tools.javac.Main. En anden mulighed er
derfor at bruge denne klasse direkte:</P>
<PRE CLASS="kode-western">public class KaldJavacInternt
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  public static void main(String[] args)</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    com.sun.tools.javac.Main overs&aelig;tter = new com.sun.tools.javac.Main();</SPAN>
<SPAN LANG="da-DK">    String[] filer = { &quot;UndersoegKlasse.java&quot; };</SPAN>
<SPAN LANG="da-DK">    overs&aelig;tter.compile( filer );</SPAN>
<SPAN LANG="da-DK">    System.out.println(&quot;f&aelig;rdig&quot;);</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE>
<HR>
<PRE CLASS="kode-western">f&aelig;rdig</PRE><P CLASS="western">
Skal man overs&aelig;tte klasser mange gange, er denne m&aring;de
langt hurtigere, idet overs&aelig;tteren k&oslash;rer i den allerede
eksisterende virtuelle maskine i stedet for at blive startet som et
nyt program. 
</P>
<P CLASS="western">Man skal v&aelig;re opm&aelig;rksom p&aring;, at
filen lib/tools.jar fra ens Java-installation skal inkluderes i
klassestien (CLASSPATH), s&aring;dan at programmet skal overs&aelig;ttes
og k&oslash;res f.eks. s&aring;ledes:</P>
<PRE CLASS="kode-western">javac -classpath /usr/local/jdk1.4/lib/tools.jar:. KaldJavacInternt.java
<SPAN LANG="da-DK">java -classpath /usr/local/jdk1.4/lib/tools.jar:. KaldJavacInternt</SPAN></PRE>
<H3 CLASS="western" STYLE="">11.4.3 <a name='afsn11.4.3'></a>Indl&aelig;se
klasser fra filsystemet</H3>
<P CLASS="western">Hvis man vil indl&aelig;se klasser fra et andet
sted end der, hvor systemet plejer at lede (f.eks. over netv&aelig;rket),
skal man definere sin egen ClassLoader.</P>
<P CLASS="western">Eksemplet herunder er en ClassLoader, der kan
indl&aelig;se klasser fra et bestemt katalog. Det f&aring;r stien til
kataloget overf&oslash;rt i konstrukt&oslash;ren, hvorefter det
opbygger en liste over de tilg&aelig;ngelige .class-filer. Denne
liste kan hentes udefra ved at kalde tilg&aelig;ngeligeKlasser().</P>
<PRE CLASS="kode-western">import java.io.*;
<SPAN LANG="da-DK">import java.util.*;</SPAN>

<SPAN LANG="da-DK">public class ClassLoaderFraKatalog extends ClassLoader {</SPAN>
<SPAN LANG="da-DK">  private Map klasser = new HashMap();</SPAN>

<SPAN LANG="da-DK">  public Set tilg&aelig;ngeligeKlasser()</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    return klasser.keySet();</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public ClassLoaderFraKatalog(String sti)</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK">    File katalog = new File(sti);</SPAN>
<SPAN LANG="da-DK">    File[] filer = katalog.listFiles();</SPAN>

<SPAN LANG="da-DK">    for (int i=0; i&lt;filer.length; i++)</SPAN>
<SPAN LANG="da-DK">    {</SPAN>
<SPAN LANG="da-DK">      File f = filer[i];</SPAN>
<SPAN LANG="da-DK">      System.out.println(f);</SPAN>
<SPAN LANG="da-DK">      String fn = f.getName();</SPAN>

<SPAN LANG="da-DK">      if (fn.endsWith(&quot;.class&quot;))</SPAN>
<SPAN LANG="da-DK">      {</SPAN>
<SPAN LANG="da-DK">        String klassenavn = fn.substring(0,fn.length()-6); <I>// fjern .class</I></SPAN>
<SPAN LANG="da-DK">        klasser.put(klassenavn,f);</SPAN>
<SPAN LANG="da-DK">      }</SPAN>
<SPAN LANG="da-DK">    }</SPAN>
<SPAN LANG="da-DK">  }</SPAN>

<SPAN LANG="da-DK">  public Class findClass(String navn) throws ClassNotFoundException</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK"><I>    //System.out.println(&quot;findClass(&quot;+navn);</I></SPAN>
<SPAN LANG="da-DK">    try {</SPAN>
<SPAN LANG="da-DK">      File f = (File) klasser.get(navn);</SPAN>
<SPAN LANG="da-DK">      if (f==null) throw new IllegalArgumentException(&quot;Ukendt klasse: &quot;+navn);</SPAN>

<SPAN LANG="da-DK">      byte[] b = new byte[(int) f.length()];</SPAN>
<SPAN LANG="da-DK">      FileInputStream fis = new FileInputStream(f);</SPAN>
<SPAN LANG="da-DK">      fis.read(b);</SPAN>
<SPAN LANG="da-DK">      return defineClass(navn, b, 0, b.length);</SPAN>
<SPAN LANG="da-DK">    } catch (Exception e) {</SPAN>
<SPAN LANG="da-DK">      System.out.println(&quot;findClass() fejl:&quot;+e.getMessage());</SPAN>
<SPAN LANG="da-DK">      throw new ClassNotFoundException(e.getMessage());</SPAN>
<SPAN LANG="da-DK">    }</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE>
<P CLASS="western" STYLE="">Herunder et
program, der benytter ClassLoaderFraKatalog:</P>
<PRE CLASS="kode-western">import java.util.*;

<SPAN LANG="da-DK">public class BenytClassLoaderFraKatalog </SPAN>
<SPAN LANG="da-DK">{</SPAN>
<SPAN LANG="da-DK">  public static void main(String[] args) throws Exception</SPAN>
<SPAN LANG="da-DK">  {</SPAN>
<SPAN LANG="da-DK"><I>    // indl&aelig;s klasser fra det aktuelle katalog (.)</I></SPAN>
<SPAN LANG="da-DK">    ClassLoaderFraKatalog classLoader = new ClassLoaderFraKatalog(&quot;.&quot;);</SPAN>

<SPAN LANG="da-DK">    Set tilg&aelig;ngeligeKlasser = classLoader.tilg&aelig;ngeligeKlasser();</SPAN>
<SPAN LANG="da-DK">    System.out.println(&quot;tilg&aelig;ngeligeKlasser=&quot;+tilg&aelig;ngeligeKlasser);</SPAN>

<SPAN LANG="da-DK">    for (Iterator i=tilg&aelig;ngeligeKlasser.iterator(); i.hasNext(); )</SPAN>
<SPAN LANG="da-DK">    {</SPAN>
<SPAN LANG="da-DK">      try {</SPAN>
<SPAN LANG="da-DK">        String klassenavn = (String) i.next();</SPAN>
<SPAN LANG="da-DK">        Class klasse = classLoader.loadClass(klassenavn);</SPAN>
<SPAN LANG="da-DK">        Object objekt = klasse.newInstance();</SPAN>
<SPAN LANG="da-DK">        System.out.println(&quot;obj = &quot; + objekt );</SPAN>
<SPAN LANG="da-DK">      } catch (Throwable e) { </SPAN>
<SPAN LANG="da-DK">        e.printStackTrace();</SPAN>
<SPAN LANG="da-DK">      }</SPAN>
<SPAN LANG="da-DK">    }</SPAN>
<SPAN LANG="da-DK">  }</SPAN>
<SPAN LANG="da-DK">}</SPAN></PRE>
<HR>
<PRE CLASS="kode-western">./FindMetoder.java
<SPAN LANG="da-DK">./ClassLoaderFraKatalog.java</SPAN>
<SPAN LANG="da-DK">./Boenneintrospektion.java</SPAN>
<SPAN LANG="da-DK">./FindMetoder.class</SPAN>
<SPAN LANG="da-DK">./KaldJavacEksternt.class</SPAN>
<SPAN LANG="da-DK">./KaldJavacInternt.java</SPAN>
<SPAN LANG="da-DK">./KaldJavacEksternt.java</SPAN>
<SPAN LANG="da-DK">./UndersoegKlasse.class</SPAN>
<SPAN LANG="da-DK">./BenytClassLoaderFraKatalog.class</SPAN>
<SPAN LANG="da-DK">./UndersoegKlasse.java</SPAN>
<SPAN LANG="da-DK">./BenytClassLoaderFraKatalog.java</SPAN>
<SPAN LANG="da-DK">./ClassLoaderFraKatalog.class</SPAN>
<SPAN LANG="da-DK">./Boenneintrospektion.class</SPAN>
<SPAN LANG="da-DK">./KaldJavacInternt.class</SPAN>
<SPAN LANG="da-DK">tilg&aelig;ngeligeKlasser=[FindMetoder, ClassLoaderFraKatalog, UndersoegKlasse, BenytClassLoaderFraKatalog, KaldJavacEksternt, Boenneintrospektion, KaldJavacInternt]</SPAN>
<SPAN LANG="da-DK">obj = FindMetoder@53c015</SPAN>
<SPAN LANG="da-DK">java.lang.InstantiationException: ClassLoaderFraKatalog</SPAN>
<SPAN LANG="da-DK">        at java.lang.Class.newInstance0(Native Method)</SPAN>
<SPAN LANG="da-DK">        at java.lang.Class.newInstance(Class.java:232)</SPAN>
<SPAN LANG="da-DK">        at BenytClassLoaderFraKatalog.main(BenytClassLoaderFraKatalog.java:18)</SPAN>
<SPAN LANG="da-DK">obj = UndersoegKlasse@680a59</SPAN>
<SPAN LANG="da-DK">obj = BenytClassLoaderFraKatalog@7f5ea7</SPAN>
<SPAN LANG="da-DK">obj = KaldJavacEksternt@13fac</SPAN>
<SPAN LANG="da-DK">obj = Boenneintrospektion@4672d0</SPAN>
<SPAN LANG="da-DK">obj = KaldJavacInternt@4abc9</SPAN></PRE>
<P CLASS="western">Det ses, at det lykkes os at indl&aelig;se
klasserne og oprette objekter fra dem. 
</P>
<P CLASS="western">Eneste undtagelse er indl&aelig;sningen af klassen
ClassLoaderFraKatalog, hvor kaldet til newInstance() fejler, da
klassen ikke har en konstrukt&oslash;r uden parametre.</P>

<H2 CLASS="western">11.5 <a name='afsn11.5'></a>Videre l&aelig;sning</SPAN></H2>
<P CLASS="western">For en grundigere indf&oslash;ring end den herover
se 
</P>
<UL>
  <LI><P CLASS="western"><SPAN LANG="da-DK">Kristian Hansens bog
  'Avanceret Java-programmering', der kan hentes gratis p&aring;<BR>
  </SPAN><SPAN STYLE="font-weight: medium"><A CLASS="western" HREF="http://bog.ing.dk/"><SPAN LANG="da-DK">http://bog.ing.dk/</SPAN></A></SPAN><SPAN LANG="da-DK">.</SPAN></P>
  <LI><P CLASS="western"><SPAN LANG="da-DK">Suns dokumentation
  </SPAN><SPAN STYLE="font-weight: medium"><A CLASS="western" HREF="http://java.sun.com/docs/books/tutorial/reflect/"><SPAN LANG="da-DK">http://java.sun.com/docs/books/tutorial/reflect/</SPAN></A></SPAN><SPAN LANG="da-DK">.</SPAN></P>
</UL>



<a href='http://javabog.dk/'>javabog.dk</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel10.jsp'>&lt;&lt; forrige</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='indhold.jsp'>indhold</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kapitel12.jsp'>n&aelig;ste &gt;&gt;</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='kode/'>programeksempler</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href='../index_VP.html'>om bogen</a>
<hr>
<font size=-2>http://javabog.dk/ - <b></b> af Jacob Nordfalk.
<br>
  Licens og kopiering under <a href='http://www.linuxbog.dk/licens.html'>&Aring;ben Dokumentlicens</a> (&Aring;DL)
  hvor intet andet er nævnt (71% af værket).
</font>
<br>
Ønsker du at se de sidste 29% af dette værk (362838 tegn)
skal du købe bogen. Så får du pæne figurer og layout, stikordsregister og en trykt bog med i købet.
<!-- netlæser: Wget/1.10, autoHent: true  -->
     

</body>
</html>
