Geneste klassen in Java

1. Inleiding

Deze tutorial is een snelle en duidelijke inleiding tot geneste klassen in de Java-taal.

Simpel gezegd, Java stelt ons in staat om klassen binnen andere klassen te definiëren. Geneste klassen stellen ons in staat om klassen die slechts op één plaats worden gebruikt logisch te groeperen, beter leesbare en onderhoudbare code te schrijven en de inkapseling te vergroten.

Laten we, voordat we beginnen, eens kijken naar de verschillende soorten geneste klassen die in de taal beschikbaar zijn:

  • Statische geneste klassen
  • Niet-statische geneste klassen
  • Lokale lessen
  • Anonieme lessen

In de volgende secties gaan we elk van deze in detail bespreken.

2. Statische geneste klassen

Hier zijn een paar punten die u moet onthouden over statisch geneste klassen:

  • Net als bij statische leden behoren deze tot hun omsluitende klasse en niet tot een instantie van de klasse
  • Ze kunnen alle soorten toegangsmodificatoren in hun aangifte hebben
  • Ze hebben alleen toegang tot statische leden in de omsluitende klasse
  • Ze kunnen zowel statische als niet-statische leden definiëren

Laten we eens kijken hoe we een statische geneste klasse kunnen declareren:

openbare klasse Omsluit {privé statische int x = 1; openbare statische klasse StaticNested {private void run () {// implementatie methode}} @ Test public void test () {Enclosing.StaticNested genest = nieuwe Enclosing.StaticNested (); genest.run (); }}

3. Niet-statische geneste klassen

Hierna volgen enkele snelle punten om te onthouden over niet-statische geneste klassen:

  • Ze worden ook wel innerlijke klassen genoemd
  • Ze kunnen alle soorten toegangsmodificatoren in hun aangifte hebben
  • Net als instantievariabelen en methoden worden innerlijke klassen geassocieerd met een instantie van de omsluitende klasse
  • Ze hebben toegang tot alle leden van de omsluitende klasse, ongeacht of ze statisch of niet-statisch zijn
  • Ze kunnen alleen niet-statische leden definiëren

Hier is hoe we een innerlijke klasse kunnen verklaren:

openbare klasse Outer {openbare klasse Inner {// ...}}

Als we een geneste klasse declareren met een modifier statisch, dan is het een statisch lid. Anders is het een innerlijke klasse. Ook al is het verschil syntactisch gezien slechts één trefwoord (d.w.z. statisch), semantisch gezien is er een enorm verschil tussen dit soort geneste klassen. Instances van innerlijke klassen zijn gebonden aan de insluitende klassen en hebben daarom toegang tot hun leden. We moeten ons bewust zijn van dit probleem wanneer we selecteren of we een geneste klasse een innerlijke klasse willen maken.

Om een ​​innerlijke klasse te instantiëren, moeten we eerst de insluitende klasse instantiëren.

Laten we eens kijken hoe we dat kunnen doen:

Outer outer = nieuwe Outer (); Outer.Inner inner = outer.new Inner ();

In de volgende paragrafen gaan we enkele speciale soorten innerlijke klassen laten zien.

3.1. Lokale lessen

Lokale klassen zijn een speciaal soort innerlijke klassen - waarin de klasse wordt gedefinieerd binnen een methode of scoopblok.

Laten we een paar punten bekijken om te onthouden over dit type les:

  • Ze kunnen geen toegangsmodificatoren hebben in hun aangifte
  • Ze hebben toegang tot zowel statische als niet-statische leden in de omsluitende context
  • Ze kunnen alleen instantieleden definiëren

Hier is een snel voorbeeld:

openbare klasse NewEnclosing {void run () {class Local {void run () {// implementatie methode}} Local local = new Local (); local.run (); } @Test openbare ongeldige test () {NewEnclosing newEnclosing = new NewEnclosing (); newEnclosing.run (); }}

3.2. Anonieme lessen

Anonieme klassen kunnen worden gebruikt om een ​​implementatie van een interface of een abstracte klasse te definiëren zonder een herbruikbare implementatie te hoeven maken.

Laten we een paar punten opsommen om te onthouden over anonieme lessen:

  • Ze kunnen geen toegangsmodificatoren hebben in hun aangifte
  • Ze hebben toegang tot zowel statische als niet-statische leden in de omsluitende context
  • Ze kunnen alleen instantieleden definiëren
  • Ze zijn het enige type geneste klassen dat geen constructors kan definiëren of andere klassen of interfaces kan uitbreiden / implementeren

Om een ​​anonieme klasse te definiëren, definiëren we eerst een eenvoudige abstracte klasse:

abstracte klasse SimpleAbstractClass {abstracte leegte run (); }

Laten we nu eens kijken hoe we een anonieme klasse kunnen definiëren:

openbare klasse AnonymousInnerUnitTest {@Test openbare leegte whenRunAnonymousClass_thenCorrect () {SimpleAbstractClass simpleAbstractClass = nieuwe SimpleAbstractClass () {void run () {// methode-implementatie}}; simpleAbstractClass.run (); }}

Voor meer details kunnen we onze tutorial over anonieme klassen in Java nuttig vinden.

4. Schaduwen

De verklaring van de leden van een innerlijke klasse vormt een schaduw van die van de omringende klasse als ze dezelfde naam hebben.

In dit geval is het dit trefwoord verwijst naar de instanties van de geneste klasse en er kan naar de leden van de buitenste klasse worden verwezen met de naam van de buitenste klasse.

Laten we een snel voorbeeld bekijken:

openbare klasse NewOuter {int a = 1; statische int b = 2; openbare klasse InnerClass {int a = 3; statische finale int b = 4; public void run () {System.out.println ("a =" + a); System.out.println ("b =" + b); System.out.println ("NewOuterTest.this.a =" + NewOuter.this.a); System.out.println ("NewOuterTest.b =" + NewOuter.b); System.out.println ("NewOuterTest.this.b =" + NewOuter.this.b); }} @Test openbare ongeldige test () {NewOuter outer = nieuwe NewOuter (); NewOuter.InnerClass inner = outer.new InnerClass (); inner.run (); }}

5. Serialisatie

Om een java.io.NotSerializableException terwijl we proberen een geneste klasse te serialiseren, moeten we:

  • Declareer de geneste klasse als statisch
  • Zorg ervoor dat zowel de geneste klasse als de omsluitende klasse worden geïmplementeerd Serialiseerbaar

6. Conclusie

In dit artikel hebben we gezien wat geneste klassen zijn en wat hun verschillende typen zijn. We hebben ook gekeken hoe veldzichtbaarheid en toegangsmodificatoren verschillen tussen die verschillende typen.

Zoals altijd is de volledige implementatie van deze tutorial te vinden op GitHub.