2011-01-17 11 views
1

Bitte erklären Sie das benutzerdefinierte 'T' in der Java-Oberfläche. Es verwendet hier Generika und vom Typ 'T' nehme ich an. Wo ist dann der Typ "T" definiert?Custom Generics Erklärung

public interface TemplateBuilder<T extends TemplateBuilder> 

Antwort

7

T ist keine tatsächliche Klasse. Es wird zur Kompilierzeit abhängig von der Verwendung Ihrer Klasse TemplateBuilder bestimmt. Stellen Sie sich einfach einen Platzhalter für verschiedene mögliche Typen vor, von denen einer abhängig von Ihren Umständen ausgewählt wird.

Für ein einfacheres Beispiel, Blick auf die folgenden (aus Java Tutorial angepasst):

Stellen Sie eine Klasse Box deklarieren möchten, die einen bestimmten Typ (des Objekts in der Box zu halten) nehmen, aber Sie möchten dies unter verschiedenen Umständen wiederverwenden, um verschiedene Typen zu halten.

Anstatt also die tatsächliche Art der Befestigung der Box nehmen, erklären Sie es wie folgt:

public class Box<T> { 

    private T t; // T stands for "Type"   

    public void set(T t) { 
     this.t = t; 
    } 

    public T get() { 
     return t; 
    } 
} 

Wenn Sie es verwenden, können Sie dann so etwas wie:

Box<Integer> integerBox = new Box<Integer>(); 

Was ist die ganze Punkt, den Sie fragen könnten? Warum macht Box nicht ein Objekt?

Tatsächlich war dies vor Java 1.5 nicht möglich. Dies wurde eingeführt, um in diesen Situationen eine weitere Typensicherheit zu erreichen, und wurde im Rahmen der Sammlung eingeführt.

Der springende Punkt ist, dass ohne diesen Mechanismus, wenn stattdessen Object verwendet wurde, Sie eine bestimmte Instanz Ihrer Box nicht zwingen können, nur ganze Zahlen zu speichern. Wenn Sie andererseits die Verwendung von Ganzzahlen explizit festgelegt haben, können Sie Ihre Box für String oder andere Objekte nicht wiederverwenden, und Sie müssten eine andere Art von Box-Klasse erstellen.

Vor Java 1.5 haben Objekte wie ArrayList einfache Objekte übernommen, jedoch gab es oft Fälle von Typensicherheit zur Laufzeit, da das Programm eine Liste von Integer-Objekten annimmt und versehentlich irgendwo einen String eingefügt wird. Generika (durch dieses magische T) zwingen Typen, ohne einzuschränken, was sie sein könnten.

In Ihrem Fall T extends TemplateBuilder geht einen Schritt weiter und besagt, dass was auch immer T ist, muss es eine Klasse sein, die TemplateBuilder erweitert. Wenn dies nicht der Fall wäre, würde jede Klasse Object (die universelle Basisklasse von Java) erweitern.

+0

Ist 'einen Typ oder einen Tippfehler IntegerBox'? – HyperNeutrino

+0

Ja ... fest ... Prost. – jbx

1

T ist eine beliebige, die Object

T bedeutet ein beliebiges Objekt von TemplateBuilder erstreckt. zum Beispiel

List<T> list = new ArrayList<T>(); 

hier kann T Integer, String ... sein

und <T extends A> bedeutet jede Object T von A

1

erstreckt Dieser Typ wird definiert, wenn die Schnittstelle implementiert, dh

class StringBuilder implements TemplateBuilder<StringBuilder> {} 

BTW, siehe Klasse Enum (die Basisklasse aller Enums).

0

My Custom Generics Erklärung

Backgorund:

  1. Generika Gewohnheit werden beispielsweise immer mit Datenstrukturen bei der Verwaltung (Speicher/Abrufen) die Listen der „Dinge“
  2. Sie Ihren eigenen Typen nicht müssen tun tun, um den Code-Kontrolle als benutzerdefinierten Generika zu kompilieren enthält die Grundsätze des Polymorphismus.
  3. jedoch im Gegensatz zu den „traditionellen“ OO Prinzipien des Polymorphismus kann eine Klasse eine Liste der Dinge speichern ohne jede Beziehung mit mit dem „Dinge (s)“ es (das Grundprinzip der OO speichert wo A ist eine Super-Klasse der B-Klasse ist nicht erforderlich)
  4. Sie machen keine separaten Unterklassen für jede mögliche Art von Klasse von "Dinge", die Sie speichern möchten. 1

Beispiel

Als Beispiel betrachten die folgenden zwei Klassen, unter dem nicht verwandten sind. Dies ist ein sehr einfaches Beispiel gibt aber dennoch einen Überblick über die Prinzipien des benutzerdefinierten Generika:

/** 
* 
* Class A is a Custom Generic class that can be 'typed' 
* to any kind of class using diamond 'T' syntax. 
* 
*/ 

class A<T> 
{ 
    // The instance variable of the object type 'T' known at run time 
    T theI; 

    // The constructor passing the object type 'T' 
    A(T anI) 
    { 
    this.theI = anI; 
    } 

    // Method to return the object 'T' 
    T getT() 
    { 
    return theI; 
    } 
} 

Unten ist die Klasse B, die A dh B erstreckt sich nicht A-Klasse nicht in Beziehung steht:

/** 
* 
* Simple class which overrides the toString() 
* method from Object's class toString() method 
* 
*/ 
class B 
{ 

    @Override 
    public String toString() 
    { 
    return "B Object"; 
    } 

    public static void main(String[] args) 
    { 
    A<B> a = new A<>(new B()); 

    System.out.println(a.getT());   
    } 
} 

In Hauptmethode der Klasse B oben:

a.getT() gibt das Objekt 'T' zurück, das in diesem Beispiel vom Typ 'B' ist (Dies ist ein Beispiel für Polymorphie).

a.getT() gibt das Objekt 'T' zurück, die Methode der Objektinstanz C toString() wird IMPLICITLY aufgerufen, da sie die toString() - Methode von Object überschreibt und "B Object" ausgibt.

Der interessante Aspekt über Custom Generics und Polymorphismus zu beachten ist, dass:

Im Rahmen von kundenspezifischen Generika gibt es keine Einschränkungen für eine Beziehung zwischen den Klassen, um Polymorphismus

auszuführen z.B. Klasse B ist unabhängige bis A oben d.h Klasse B erstreckt sich nicht A.

In „traditionellen“ objektorientierte Polymorphismus Prinzipien, gibt es immer eine Anforderung Einschränkung für Klassen in irgendeiner Weise zusammenhängen. Dies ist jedoch in benutzerdefinierten Generika nicht erforderlich.2

Beispiel

public interface TemplateBuilder<T extends TemplateBuilder> 

Das obige bedeutet, dass TemplateBuilder Schnittstelle sein kann zu jeder Klasse typisiert dass TemplateBuilder erstreckt.

Nehmen wir an, Someclass TemplateBuilder erstreckt sich dann die folgende ist in Ordnung:

TemplateBuilder<SomeClass> tbRef = ... 
/* Using an Anonymous Inner Class reference to interface TemplateBuilder<SomeClass> */ 

oder

TemplateBuilder<SomeClass> tbRef = .... /* Referencing a concrete class 
that implements TemplateBuilder */