Indlejrede klasser er klasser, der erklæres som medlemmer af andre klasser eller anvendelsesområder. Nestende klasser er en måde at bedre organisere din kode på. Sig for eksempel, at du har en klasse, der ikke er indlejret (også kendt som en topklasse), der gemmer objekter i en størrelse, der kan ændres, efterfulgt af en iteratorklasse, der returnerer hvert objekt. I stedet for at forurene det øverste klasses navneområde, kan du erklære iterator-klassen som medlem af den resizable array-samlingsklasse. Dette fungerer, fordi de to er tæt beslægtede.
I Java er indlejrede klasser kategoriseret som enten statiske medlemsklasser eller indre klasser. Indre klasser er ikke-statiske medlemsklasser, lokale klasser eller anonyme klasser. I denne vejledning lærer du at arbejde med statiske medlemsklasser og de tre typer indre klasser i din Java-kode.
Undgå hukommelseslækage i indlejrede klasser
Se også Java-tip, der er knyttet til denne tutorial, hvor du lærer, hvorfor indlejrede klasser er sårbare over for hukommelseslækage.
Statiske klasser i Java
I min Java 101 tutorial Klasser og objekter i Java, du lærte at erklære statiske felter og statiske metoder som medlemmer af en klasse. I klasse- og objektinitialisering i Java lærte du, hvordan man erklærer statiske initialiserere som medlemmer af en klasse. Nu lærer du at erklære statiske klasser. Formelt kendt som statiske medlemsklasser, dette er indlejrede klasser, som du erklærer på samme niveau som disse andre statiske enheder ved hjælp af statisk
nøgleord. Her er et eksempel på en statisk erklæring om medlemsklasse:
klasse C {statisk int f; statisk tomrum m () {} statisk {f = 2; } statisk klasse D {// medlemmer}}
Dette eksempel introducerer topklasse C
med statiske felt f
, statisk metode m ()
, en statisk initialisering og en statisk medlemsklasse D
. Læg mærke til det D
er medlem af C
. Det statiske felt f
, statisk metode m ()
og den statiske initialisering er også medlemmer af C
. Da alle disse elementer hører til klassen C
, det er kendt som omsluttende klasse. Klasse D
er kendt som lukket klasse.
Indhegnings- og adgangsregler
Selv om den er lukket, kan en statisk medlemsklasse ikke få adgang til den omgivende klasses instansfelter og påberåbe sig dens instansmetoder. Det kan dog få adgang til den omgivende klasses statiske felter og påberåbe sig dens statiske metoder, selv de medlemmer, der er erklæret privat
. For at demonstrere erklærer Listing 1 en Omslutningsklasse
med en indlejret SMC-klasse
.
Fortegnelse 1. Erklæring om en statisk medlemsklasse (EnclosingClass.java, version 1)
klasse EnclosingClass {privat statisk streng s; privat statisk tomrum m1 () {System.out.println (s); } statisk ugyldigt m2 () {SMClass.accessEnclosingClass (); } static class SMClass {static void accessEnclosingClass () {s = "Opkaldt fra SMClasss accessEnclosingClass () -metode"; m1 (); } ugyldig adgangEnclosingClass2 () {m2 (); }}}
Listing 1 erklærer en klasse på øverste niveau ved navn Omslutningsklasse
med klassefelt s
, klassemetoder m1 ()
og m2 ()
, og statisk medlemsklasse SMClass
. SMC-klasse
erklærer klassemetode accessEnclosingClass ()
og instansmetode accessEnclosingClass2 ()
. Bemærk følgende:
m2 ()
påkaldelse afSMC-klasse
'saccessEnclosingClass ()
metoden kræverSMC-klasse.
præfiks fordiaccessEnclosingClass ()
erklæresstatisk
.accessEnclosingClass ()
er i stand til at få adgangOmslutningsklasse
'ss
felt og kalde densm1 ()
metode, selvom begge er blevet erklæretprivat
.
Liste 2 viser kildekoden til en SMCDemo
applikationsklasse, der viser, hvordan man påberåber sig SMC-klasse
's accessEnclosingClass ()
metode. Det viser også, hvordan man kan instantere SMC-klasse
og påberåbe sig dens accessEnclosingClass2 ()
eksempel metode.
Fortegnelse 2. Påkaldelse af en statisk medlems klasses metoder (SMCDemo.java)
public class SMCDemo {public static void main (String [] args) {EnclosingClass.SMClass.accessEnclosingClass (); EnclosingClass.SMClass smc = ny EnclosingClass.SMClass (); smc.accessEnclosingClass2 (); }}
Som vist i liste 2, hvis du vil påberåbe sig en topklasses metode fra en lukket klasse, skal du forudse den lukkede klasses navn med navnet på den lukkende klasse. For at starte en lukket klasse skal du ligeledes foran navnet på den klasse med navnet på den lukkede klasse. Du kan derefter påberåbe sig instansmetoden på normal måde.
Kompilér lister 1 og 2 som følger:
javac * .java
Når du kompilerer en omsluttende klasse, der indeholder en statisk medlemsklasse, opretter kompilatoren en klassefil til den statiske medlemsklasse, hvis navn består af dens vedlagte klassenavn, et dollartegnetegn og det statiske medlemsklassens navn. I dette tilfælde resulterer kompilering i EnclosingClass $ SMCClass.class
og EnclosingClass.class
.
Kør applikationen som følger:
java SMCDemo
Du skal overholde følgende output:
Opkaldt fra SMClass's accessEnclosingClass () metode Opkaldt fra SMClass's accessEnclosingClass () metode
Eksempel: Statiske klasser og Java 2D
Java'er standard klassebibliotek er et runtime-bibliotek med klassefiler, der gemmer kompilerede klasser og andre referencetyper. Biblioteket indeholder adskillige eksempler på statiske medlemsklasser, hvoraf nogle findes i Java 2D geometriske formklasser placeret i java.awt.geom
pakke. (Du lærer om pakker i det næste Java 101 vejledning.)
Det Ellipse2D
klasse fundet i java.awt.geom
beskriver en ellipse, der er defineret af et indramningsrektangel i form af et (x, y) øverste venstre hjørne sammen med bredde- og højdeomfang. Det følgende kodefragment viser, at denne klasses arkitektur er baseret på Flyde
og Dobbelt
statiske medlemsklasser, som begge underklasser Ellipse2D
:
offentlig abstrakt klasse Ellipse2D udvider RectangularShape {offentlig statisk klasse Float udvider Ellipse2D implementerer Serialiserbar {offentlig float x, y, bredde, højde; public Float () {} public Float (float x, float y, float w, float h) {setFrame (x, y, w, h); } offentlig dobbelt getX () {retur (dobbelt) x; } // yderligere instansmetoder} offentlig statisk klasse Dobbelt udvider Ellipse2D implementerer Serialiserbar {offentlig dobbelt x, y, bredde, højde; offentlig dobbelt () {} offentlig dobbelt (dobbelt x, dobbelt y, dobbelt w, dobbelt h) {setFrame (x, y, w, h); } offentlig dobbelt getX () {return x; } // yderligere instansmetoder} offentlig boolsk indeholder (dobbelt x, dobbelt y) {// ...} // yderligere instansmetoder delt af Float, Double og andre // Ellipse2D-underklasser}
Det Flyde
og Dobbelt
klasser udvides Ellipse2D
, der giver flydende punkt og dobbelt præcision flydende punkt Ellipse2D
implementeringer. Udviklere bruger Flyde
for at reducere hukommelsesforbruget, især fordi du muligvis har brug for tusinder eller flere af disse objekter for at konstruere en enkelt 2D-scene. Vi bruger Dobbelt
når der kræves større nøjagtighed.
Du kan ikke instantiere det abstrakte Ellipse2D
klasse, men du kan instantiere enten Flyde
eller Dobbelt
. Du kan også udvide Ellipse2D
til at beskrive en brugerdefineret form, der er baseret på en ellipse.
Lad os som et eksempel sige, at du vil introducere en Circle2D
klasse, som ikke er til stede i java.awt.geom
pakke. Følgende kodefragment viser, hvordan du opretter et Ellipse2D
objekt med en floating-point implementering:
Ellipse2D e2d = ny Ellipse2D.Float (10.0f, 10.0f, 20.0f, 30.0f);
Det næste kodefragment viser, hvordan du opretter et Ellipse2D
objekt med en dobbeltpræcisions implementering af flydende punkt:
Ellipse2D e2d = ny Ellipse2D.Double (10.0, 10.0, 20.0, 30.0);
Du kan nu påberåbe sig en af de metoder, der er angivet i Flyde
eller Dobbelt
ved at påkalde metoden på den returnerede Ellipse2D
reference (f.eks. e2d.getX ()
). På samme måde kan du påberåbe dig hvilken som helst af de metoder, der er fælles for Flyde
og Dobbelt
, og som er erklæret i Ellipse2D
. Et eksempel er:
e2d.contains (2.0, 3.0)
Det fuldender introduktionen til statiske medlemsklasser. Dernæst ser vi på indre klasser, som er ikke-statiske medlemsklasser, lokale klasser eller anonyme klasser. Du lærer at arbejde med alle tre typer af indre klasser.
download Hent koden Download kildekoden for eksempler i denne vejledning. Oprettet af Jeff Friesen til JavaWorld.Indre klasser, type 1: Ikke-statiske medlemsklasser
Du har lært tidligere i Java 101 serie, hvordan man erklærer ikke-statiske (instans) felter, metoder og konstruktører som medlemmer af en klasse. Du kan også erklære ikke-statiske medlemsklasser, som er indlejrede ikke-statiske klasser, som du erklærer på samme niveau som instansfelter, metoder og konstruktører. Overvej dette eksempel:
klasse C {int f; ugyldigt m () {} C () {f = 2; } klasse D {// medlemmer}}
Her introducerer vi topklasse C
med instansfelt f
, eksempel metode m ()
, en konstruktør og ikke-statisk medlemsklasse D
. Alle disse enheder er medlemmer af klassen C
, som omslutter dem. Men i modsætning til i det foregående eksempel er disse instanssenheder tilknyttet tilfælde afC
og ikke med C
klasse selv.
Hver forekomst af den ikke-statiske medlemsklasse er implicit forbundet med en forekomst af dens omsluttende klasse. Den ikke-statiske medlemsklasse's instansmetoder kan kalde den omgivende klasses instansmetoder og få adgang til dens instansfelter. For at demonstrere denne adgang erklærer Listing 3 en Omslutningsklasse
med en indlejret NSM-klasse
.
Fortegnelse 3. Erklær en omsluttende klasse med en indlejret ikke-statisk medlemsklasse (EnclosingClass.java, version 2)
klasse EnclosingClass {private String s; privat tomrum m () {System.out.println (s); } klasse NSMClass {void accessEnclosingClass () {s = "Opkaldt fra NSMClass's accessEnclosingClass () -metode"; m (); }}}
Listing 3 erklærer en topklasse navngivet Omslutningsklasse
med instansfelt s
, eksempel metode m ()
og ikke-statisk medlemsklasse NSM-klasse
. Desuden, NSMClass
erklærer instansmetode accessEnclosingClass ()
.
Fordi accessEnclosingClass ()
er ikke-statisk, NSM-klasse
skal instantieres, før denne metode kan kaldes. Denne instantiering skal finde sted via en forekomst af Omslutningsklasse
, som vist i liste 4.
Notering 4. NSMCDemo.java
public class NSMCDemo {public static void main (String [] args) {EnclosingClass ec = new EnclosingClass (); ec.new NSMClass (). accessEnclosingClass (); }}
Liste 4's hoved ()
metoden instantieres først Omslutningsklasse
og gemmer sin reference i lokal variabel ec
. Det hoved ()
metoden bruger derefter Omslutningsklasse
henvisning som et præfiks til ny
operatør for at instantiere NSM-klasse
. Det NSM-klasse
reference bruges derefter til at ringe accessEnclosingClass ()
.
Skal jeg bruge 'nyt' med en henvisning til den vedlagte klasse?
Præfiksering ny
med en henvisning til den vedlagte klasse er sjælden. I stedet kalder du typisk en lukket klasses konstruktør fra en konstruktør eller en instansmetode i dens lukkende klasse.
Kompilér liste 3 og 4 som følger:
javac * .java
Når du kompilerer en omsluttende klasse, der indeholder en ikke-statisk medlemsklasse, opretter kompilatoren en klassefil til den ikke-statiske medlemsklasse, hvis navn består af dens vedlagte klassenavn, et dollartegnetegn og den ikke-statiske medlemsklasse navn. I dette tilfælde resulterer kompilering i EnclosingClass $ NSMCClass.class
og EnclosingClass.class
.
Kør applikationen som følger:
java NSMCDemo
Du skal overholde følgende output:
Kaldes fra NSMClass's accessEnclosingClass () -metode
Hvornår (og hvordan) at kvalificere 'dette'
En lukket klasses kode kan få en henvisning til dens lukkende klasse-forekomst ved at kvalificere det reserverede ord det her
med den vedlagte klasses navn og medlemsadgangsoperatøren (.
). For eksempel hvis kode inden for accessEnclosingClass ()
behov for at få en henvisning til dens Omslutningsklasse
eksempel, ville det specificere EnclosingClass.this
. Da compileren genererer kode for at udføre denne opgave, er det sjældent at specificere dette præfiks.
Eksempel: Ikke-statiske medlemsklasser i HashMap
Standardklassebiblioteket inkluderer ikke-statiske medlemsklasser såvel som statiske medlemsklasser. I dette eksempel ser vi på HashMap
klasse, som er en del af Java Collections Framework i java.util
pakke. HashMap
, der beskriver en hash-tabelbaseret implementering af et kort, inkluderer flere ikke-statiske medlemsklasser.
F.eks Nøglesæt
ikke-statisk medlemsklasse beskriver et sæt-baseret udsigt af nøglerne på kortet. Det følgende kodefragment vedrører det vedlagte Nøglesæt
klasse til sin HashMap
omsluttende klasse:
offentlig klasse HashMap udvider AbstractMap implementerer Map, Cloneable, Serializable {// forskellige medlemmer endelig klasse KeySet udvider AbstractSet {// forskellige medlemmer} // forskellige medlemmer}
Det og
syntakser er eksempler på generiske lægemidler, en række relaterede sprogfunktioner, der hjælper kompilatoren med at håndhæve typesikkerhed. Jeg introducerer generiske lægemidler i en kommende Java 101 vejledning. For nu skal du bare vide, at disse syntakser hjælper kompilatoren med at håndhæve typen af nøgleobjekter, der kan gemmes på kortet og i nøglesættet, og typen af værdiobjekter, der kan gemmes på kortet.
HashMap
giver en keySet ()
metode, der instantierer Nøglesæt
når det er nødvendigt, og returnerer denne forekomst eller en cachelagret forekomst. Her er den komplette metode: