Lapper
| Man fristes til at sige, at det ikke er nogen tilfældighed at
wrapper (dk.: en person, der pakker ting ind) rimer på lapper (i
det mindste på papiret). Wrapper klasser eksisterer primært
for at lappe på Java's manglende objektorientering. Det drejer sig
om Java's primitive typer: int,
char, boolean,
double osv. Erklærer
man f.eks. en integer variabel:
|
|
|
| ligger der et problem og lurer. x
er hverken et objekt eller en reference til et objekt - den er bare en
variabel, der kan antage en talværdi. I de fleste situationer er
det ikke noget problem, og flere vil endog betragte det som objektorienteret
hysteri at gøre det til et problem. Desværre er det et temlig
upraktisk problem når det endelig viser sig.
|
Container
| Behovet for at variable som x
skulle være et objekt opstår primært i forbindelse med
containere. F.eks. kan Collection-klasser i java.util
kun arbejde med objekter, så en linket liste af heltal kan ikke
umiddelbart lade sig gøre.
|
| F.eks. kan man ikke placere tallene fra 1 til 10 i en linket liste med:
|
|
LinkedList list = new LinkedList();
for ( int i=1; i<=10; i++ )
list.add( i ); |
|
| da LinkedList's
add-metode kun
kan tage et Object
som parameter.
|
| Det er i sådanne situationer man kan bruge wrappere. Vi udskifter
den sidste linie med:
|
|
list.add( new Integer( i ) ); |
|
Integer
| Vi anvender her set-konstruktoren for klassen Integer.
Integer er en wrapper
klasse, dvs. en klasse hvis instanser kun har til formål at indeholde
noget andet (pakke det ind). Man kunne også kalde det en "single-container",
fordi den kun kan indeholde ét element.
|
| Mulighederne for at arbejde med en Integer
er meget begrænsede - wrapper-klasserne er alle immutable.
Integer-objektet
er kun en indpakning, og vil man bruge talværdien til noget, må
man hente den ud igen.
|
|
Antag f.eks. at vi ønsker at gennemløbe listen og inkrementere
samtlige tal. Så kan man naturligvis godt glemme alt om:
|
|
for ( int i=1; i<=10; i++ )
((Integer) list.get( i ))++; |
|
| og der er som nævnt ingen metoder i Integer
der kan hjælpe os. Så følgende er også udelukket:
|
|
for ( int i=1; i<=10; i++ )
((Integer) list.get( i )).inc(); |
|
| Derimod skal vi igennem følgende for at få den ønskede
inkrementering:
|
|
for ( int i=0; i<list.size(); i++ ) {
int tal = ((Integer) list.get( i )).intValue();
list.set( i, new Integer( tal+1 ) );
}
|
|
| Først skal vi hente talværdien ud fra wrapper'en. Så
skal der laves en ny wrapper til den nye værdi, og den sættes
ind i listen hvor den gamle wrapper var.
|
Andet end wrappere
| Som man kan se har wrappere ikke det store at byde på, når
det drejer sig om at arbejde med deres indhold. Dermed er historien om
wrappere dog ikke slut. Klasserne har andre ting at byde på, vedrørende
de primitive typer, de på sin vis repræsenterer.
|
| Inden vi studerer disse muligheder vil vi først have et overblik
over hvilke wrappere der findes, og hvilke primitive typer de repræsenterer:
|
|
Wrapper
|
Type
|
Boolean |
boolean |
Character |
char |
Byte |
byte |
Short |
short |
Integer |
int |
Long |
long |
Float |
float |
Double |
double |
|
| Man bemærker at wrapper klasserne for char
og int har typens
uforkortede navn.
|
| Klasserne befinder sig i java.lang,
og kan som andre klasser indplaceres i et nedarvnings-hierarki:
|
Figur 1:
wrapper klasserne
|
|
| Man kan her undre sig over, at det ikke er Number,
men dens subklasser, der implementer Comparable.
Selv om Number har
andre subklasser end de her nævnte, realiserer de alle Comparable.
|
|
|
| Alle wrappere har følgende konstruktorer:
|
Konstruktorer
|
En set-konstruktor, der tager den primitive type som parameter
En konstruktor, der tager en tekststreng som parameter, og konverterer
denne tekst til den primitive datatype (Character
har dog ikke denne konstruktor). Hvis det ikke er muligt at konvertere
teksten kaster den en NumberFormatException.
|
| Da wrappere er immutable
har de naturligvis ikke nogen set-metoder, men de har alle en get-metode:
|
get-metode
|
|
| hvor <type> er den primitive types
navn. F.eks. har Integer
følgende get-metode:
|
|
|
|
Number's
subklasser
|
| Alle de numeriske wrappere har følgende statiske metoder, der
ofte bruges til at konvertere et tekst-input til en talværdi:
|
|
<type> parse<type>( String s )
|
|
| F.eks. har Integer
metoden:
|
|
|
| idet man følger den normale navne-konvention med store og små
bogstaver i metode-navne.
|
| Alle numeriske wrappere har også to statiske konstanter:
|
|
<type> MAX_VALUE
<type> MIN_VALUE |
|
| som er henholdsvis den største og den mindste værdi for
den pågældende primitive type.
|
|
|
| Heltals-wrapperne: Integer
og Long har nogle
kraftfulde statiske toString-metoder
der retter sig mod andre talsystemer:
|
Binær, octal og hex
|
String toBinaryString( <type> value )
String toOctalString( <type> value )
String toHexString( <type> value )
|
|
| Mere generelt har Integer
og Long en statiske
metode, der tager grundtallet (kaldes radix),
som parameter:
|
|
String toString( <type> value, int radix ); |
|
| Der anvendes 2. komplement, idet der ved negative tal fyldes ud til
den primitive types "binære bredde".
|
|
|
| De numeriske wrappere har også andre statiske konstanter og metoder,
men vi vil udelade dem her, da de enten er meget specielle eller redundante.
|
|
Character
|
| Første og fremmest har Character
to statiske metoder til at at konvertere et tegn til henholdsvis stort
eller lille:
|
|
char toLowerCase()
char toUpperCase() |
|
| Dernæst har Character
en lang række boolske metoder til klassifikation af tegn. Vi vil
her nævne de mest relevante:
|
|
boolean isDigit( char c ) |
Om c er et ciffer ('0'...'9') |
boolean isLetter( char c) |
Om c er et bogstav |
boolean isLetterOrDigit( char c ) |
Om c er et bogstav eller et ciffer |
boolean isLowerCase( char c ) |
Om c er et lille bogstav |
boolean isUpperCase( char c ) |
Om c er et stort bogstav |
boolean isWhiteSpace( char c ) |
Om c er et mellemrum, tabulering er linieskift |
|
|
|
Nødvendigt onde
| Set med objektorienterede øjne er Java's wrappere megen dårligdom
samlet på et sted, men vil man skrive Java-programmer, er der ingen
vej uden om at bruge dem. De er der for at løse nogle problemer
der er reelle nok.
|
|
|
|
|
| |