Java Inner Classes uitgelegd: Ontwerp, Syntaxis en Praktische Toepassingen
Geneste klassen (Nested Classes)
In Java, net zoals methodes, kan een klasse een andere klasse als lid hebben. Het schrijven van een klasse binnen een andere klasse is in Java toegestaan. De klasse die binnenin geschreven wordt, heet de geneste klasse (nested class), en de klasse die de innerlijke klasse bevat, heet de outer klasse (outer class).
Syntaxis
Hier is de syntaxis om een geneste klasse te schrijven. Hier is de klasse Outer_Demo de outer klasse en de klasse Inner_Demo de geneste klasse.
class Outer_Demo {
class Inner_Demo {
}
}
Geneste klassen worden verdeeld in twee typen:
- Niet-statische geneste klassen – Dit zijn de niet-statische leden van een klasse.
- Statische geneste klassen – Dit zijn de statische leden van een klasse.
Inner Classes (Niet-statische Geneste Klassen)
Inner classes zijn een beveiligingsmechanisme in Java. We weten dat een klasse niet kan worden geassocieerd met de toegangsmofifier private, maar als we de klasse als lid van een andere klasse hebben, dan kan de inner class private worden gemaakt. Dit wordt ook gebruikt om toegang te krijgen tot de private leden van een klasse.
Inner classes zijn van drie typen, afhankelijk van hoe en waar je ze definieert:
- Inner Class (gewone inner class)
- Method-local Inner Class
- Anonymous Inner Class
Inner Class
Het maken van een inner class is vrij simpel. Je hoeft gewoon een klasse binnen een klasse te schrijven. In tegenstelling tot een gewone klasse, kan een inner class private zijn, en zodra je een inner class private declareert, kan deze niet worden benaderd vanuit een object buiten de klasse.
Voorbeeld
class Outer_Demo {
int num;
// inner class
private class Inner_Demo {
public void print() {
System.out.println("Dit is een inner class");
}
}
// Toegang tot de inner class vanuit een methode
void display_Inner() {
Inner_Demo inner = new Inner_Demo();
inner.print();
}
}
public class My_class {
public static void main(String args[]) {
// Instantiëren van de outer class
Outer_Demo outer = new Outer_Demo();
// Aanroepen van de display_Inner() methode
outer.display_Inner();
}
}
Hier zie je dat Outer_Demo de outer class is, Inner_Demo de inner class, display_Inner() de methode waarin we de inner class instantiëren, en deze methode wordt aangeroepen vanuit de main-methode.
Als je het bovenstaande programma compileert en uitvoert, krijg je het volgende resultaat:
Dit is een inner class.
Toegang tot Private Leden
Zoals eerder gezegd, worden inner classes ook gebruikt om toegang te krijgen tot de private leden van een klasse. Stel, een klasse heeft private leden om ze te benaderen. Schrijf een inner class erin, geef de private leden terug vanuit een methode binnen de inner class, zeg getValue(), en roep ten slotte vanuit een andere klasse (waarvan je de private leden wilt benaderen) de getValue()-methode van de inner class aan.
Om de inner class te instantiëren, moet je eerst de outer class instantiëren. Daarna, met het object van de outer class, is dit de manier om de inner class te instantiëren:
Outer_Demo outer = new Outer_Demo(); Outer_Demo.Inner_Demo inner = outer.new Inner_Demo();
Voorbeeld
class Outer_Demo {
// private variabele van de outer class
private int num = 175;
// inner class
public class Inner_Demo {
public int getNum() {
System.out.println("Dit is de getNum-methode van de inner class");
return num;
}
}
}
public class My_class2 {
public static void main(String args[]) {
// Instantiëren van de outer class
Outer_Demo outer = new Outer_Demo();
// Instantiëren van de inner class
Outer_Demo.Inner_Demo inner = outer.new Inner_Demo();
System.out.println(inner.getNum());
}
}
Resultaat:
Dit is de getNum-methode van de inner class: 175
Method-local Inner Class
In Java kun je een klasse binnen een methode schrijven; dit is een lokaal type. Net als lokale variabelen is het bereik van de inner class beperkt tot de methode.
Een method-local inner class kan alleen worden geïnstantieerd binnen de methode waar de inner class gedefinieerd is.
Voorbeeld
public class Outerclass {
// instantie-methode van de outer class
void my_Method() {
int num = 23;
// method-local inner class
class MethodInner_Demo {
public void print() {
System.out.println("Dit is method inner class " + num);
}
}
// einde van inner class
// Toegang tot de inner class
MethodInner_Demo inner = new MethodInner_Demo();
inner.print();
}
public static void main(String args[]) {
Outerclass outer = new Outerclass();
outer.my_Method();
}
}
Resultaat:
Dit is method inner class 23
Anonymous Inner Class
Een inner class die zonder klassenaam wordt gedeclareerd, heet een anonymous inner class. Bij anonymous inner classes declareren en instantiëren we ze tegelijkertijd. Over het algemeen worden ze gebruikt wanneer je een methode van een klasse of een interface wilt overschrijven.
Syntaxis
AnonymousInner an_inner = new AnonymousInner() {
public void my_method() {
........
........
}
};
Voorbeeld: Methode van een klasse overschrijven
abstract class AnonymousInner {
public abstract void mymethod();
}
public class Outer_class {
public static void main(String args[]) {
AnonymousInner inner = new AnonymousInner() {
public void mymethod() {
System.out.println("Dit is een voorbeeld van anonymous inner class");
}
};
inner.mymethod();
}
}
Resultaat:
Dit is een voorbeeld van anonymous inner class
Op dezelfde manier kun je de methodes van een concrete klasse en een interface overschrijven met een anonymous inner class.
Anonymous Inner Class als Argument
Over het algemeen, als een methode een object van een interface, een abstracte klasse of een concrete klasse accepteert, dan kunnen we de interface implementeren, de abstracte klasse uitbreiden en het object aan de methode doorgeven. Als het een klasse is, kunnen we het direct doorgeven.
Maar in alle drie gevallen kun je een anonymous inner class aan de methode doorgeven. Hier is de syntaxis:
obj.my_Method(new My_Class() {
public void Do() {
.....
.....
}
});
Voorbeeld
// interface
interface Message {
String greet();
}
public class My_class {
// methode die object van interface Message accepteert
public void displayMessage(Message m) {
System.out.println(m.greet() + ", Dit is een voorbeeld van anonymous inner class als argument");
}
public static void main(String args[]) {
// Instantiëren van de klasse My_class
My_class obj = new My_class();
// Doorgeven van een anonymous inner class als argument
obj.displayMessage(new Message() {
public String greet() {
return "Hallo";
}
});
}
}
Resultaat:
Hallo, Dit is een voorbeeld van anonymous inner class als argument
Static Nested Class
geen toegang tot de instantievariabelen en -methodes van de outer class.
Syntaxis
class MyOuter {
static class Nested_Demo {
}
}
Het instantiëren van een statische geneste klasse verschilt iets van het instantiëren van een inner class.
Voorbeeld
public class Outer {
static class Nested_Demo {
public void my_method() {
System.out.println("Dit is mijn geneste klasse");
}
}
public static void main(String args[]) {
Outer.Nested_Demo nested = new Outer.Nested_Demo();
nested.my_method();
}
}
Resultaat:
Dit is mijn geneste klasse
Java
- Java's final-sleutelwoord begrijpen: variabelen, methoden en klassen
- Java instanceof operator: een uitgebreide gids
- Java geneste en inner classes meesteren: typen, voorbeelden en best practices
- Java geneste static classes begrijpen: gebruik, verschillen en voorbeelden
- Java anonieme inner classes meesteren: definitie, syntax en praktische voorbeelden
- Java Singleton patroon uitgelegd: hoe veilig te implementeren en gebruiken
- Java Reflectie meesteren: klassen, methoden en velden inspecteren tijdens runtime
- Java ObjectOutputStream: Serialisatie, methoden en praktische voorbeelden
- Java Generics: Herbruikbare, type-veilige code bouwen
- Java-bestandsbewerkingen onder de knie krijgen met java.io – Aanmaken, lezen, schrijven en verwijderen
- Java Onder de Knie: Objects, Classes en Kern OOP Concepten