Ein generischer Poolbuilder
Mit der Java-Version 5 (1.5) wurden ja auch die Generics in die Sprache Java eingeführt, das sind diese Angaben in Spitzen Klammern, die jetzt bei Sammlungsklassen geschrieben werden müssen also: Map, sonst hagelt es Compiler-Warnungen. Das folgende kleine Beispiel zeigt, wie sich Generics auch in eigenen Klassen produktiv einsetzen lassen:
Nehmen wir mal an, wir wollen einen Pool von Anwendungsobjekten, also Produkten oder Forumsbeiträgen oder ähnlichem verwalten, um daraus beispielsweise Empfehlungen für bestimmte Usecases zu bilden. Die Verwaltung der Objekte in den Pools ist immer ähnlich, allerdings sind die zu verwaltenden Objekte unterschiedlich und lassen sich nicht in eine Klassenhierarchie bringen. Hier könnte ein generischer PoolBuilder beispielsweise so aussehen:
package de.java1.blog.poolbuilder; import java.util.List; /** * Generic PoolBuilder * @author Hans Joachim Herbertz * @created 09.02.2008 */ public abstract class PoolBuilder{ List pool = null; public List getPool() { // do work common to all T's // do special work for each T for (T item : pool) { doMoreWithItem(item); } return pool; } protected abstract void doMoreWithItem(T item); }
Das "<T>" bezeichnet hier die Klasse, für die der PoolBuilder geeignet ist. Wenn wir nun eine konkrete Implementierung für beispielsweise eine Klasse Product ableiten, könnte das so aussehen:
package de.java1.blog.poolbuilder; import java.util.List; /** * PoolBuilder for Product * @author Hans Joachim Herbertz * @created 09.02.2008 */ public class ProductPoolBuilder extends PoolBuilder{ public ProductPoolBuilder(List productList) { this.pool=productList; } @Override protected void doMoreWithItem(Product item) { // do things with product here.. } }
Wie man sieht, erweitert diese Klasse die Klasse PoolBuilder für den Type Product (PoolBuilder<Product>). Daher wird quasi das T aus der Basisklasse durch Product ersetzt, und wir können überall, wo T stand, können wir nun ohne weiteres Product verwenden. Insbesondere können wir die productList direkt dem Objekt: pool zuweisen (Zeile: 12), und auch die Signatur der überschrieben Methode erfordert nun die Klasse Product.
Leicht lassen sich weitere spezielle Implementierungen für andere Datenklassen erzeugen. Das alles ist natürlich viel eleganter und durchsichtiger als wie früher auf Basis von java.lang.Object zu arbeiten, um dann in den Tochterklassen freihändig zu casten.
Ps. Statt T kann auch jeder andere Buchstabe verwendet werden.