Wie Generics richtig benutzen ?

Diskutiere Wie Generics richtig benutzen ? im Java Basics - Anfänger-Themen Bereich.
X

xlChaos

Moin zusammen !

Wir haben in unserer vorletzten Vorlesung etwas zum Thema Generics& LinkedList gelernt.

So wie ich das verstanden habe, werden Generics(<T>) einfach nur dafür benutzt um festzulegen, welcher Datentyp die Elemente(z.B. in einer LinkedList )beinhalten.

Generics werden in spitze Klammern gesetzt und nach einem Klassennamen geschrieben. Danach kann man den Klassennamen bei der Erzeugung eines Objekts einfach durch den Typparameter T ersetzen und das wars.

Wir haben einen Aufgabenzettel bekommen wo wir erst 3 Klassen schreiben sollten :

Student ( nachname,vorname, jahrgang, matnr)
Node (next, Student data)
LinkedList (root, last, current <- Alle vom Typ Node)

Es gibt eine Test Klasse die wie folgt geschrieben ist:

Java:
public class TestLinkedList<T> {

    public static void main(String[] args) {
        Student first = new Student ("Mueller", "Markus", 1990,1);
        Student second = new Student ("Meier", "Michael", 1991,2);
        Student third = new Student ("Schmidt","Sebastian",1992,3);
        
        LinkedList studenten = new LinkedList();
    
        studenten.append(first);
        studenten.append(second);
        studenten.append(third);
        studenten.append(first);
        
        
        if (studenten.isEmpty())
            return;
        Student s = (Student)studenten.getFirst();
        System.out.println(s);
        
        while (studenten.hasNext()) {
            s = (Student)studenten.getNext();
            System.out.println(s);
        }
        studenten.getFirst();
        System.out.println(studenten.hasNext());
        System.out.println(studenten.getLast());
    }

}
So wie ich das hier geschrieben habe funktioniert es auch. Wir hatten die Aufgabe in den Klassen Node und LinkedList, alle Studentenobjekte mit den Generics zu ersetzen, so dass die main Klasse auch funktioniert danach.

Ich musste hier nur 2 mal von Object auf Student typecasten, was irgendwie glaube nicht so toll ist und unser eigentliches Ziel war ...
Ohne die Typecasts kam die Fehlermeldung : Cannot convert from Object to Student

Wie löse ich das mit Generics in der Mainmethode ? Ich habe <T> ja bereits beim Klassennamen hingeschrieben, nur egal wo ich ein T setze, kommt immer die Fehlermeldung mit static reference to a non-static field...

Ich will jetzt auch nicht die Lösung vorgekaut bekommen sondern freue mich über Tipps und Hinweise, wie ich das jetzt gelöst bekomme.

Vielen Dank !
 
T

temi

LinkedList<Student> studenten = new LinkedList<>();

Deine Version entspricht im Prinzip LinkedList<Object> studenten = new LinkedList<>();

So ganz hab ich die Aufgabe nicht verstanden. Sollt ihr die Klasse mit der main() jetzt anpassen oder soll sie unverändert bleiben?

Edit: Ach so, und was das class TestLinkedList<T> soll erschließt sich mir nicht. Ist das "ich schreib einfach mal überall <T> hin und schau was passiert", oder wie?
 
Zuletzt bearbeitet:
T

temi

So wie ich das verstanden habe, werden Generics(<T>) einfach nur dafür benutzt um festzulegen, welcher Datentyp die Elemente(z.B. in einer LinkedList )beinhalten.
Das stimmt so. T steht sozusagen als Platzhalter für den tatsächlichen Typen.

Generics werden in spitze Klammern gesetzt und nach einem Klassennamen geschrieben. Danach kann man den Klassennamen bei der Erzeugung eines Objekts einfach durch den Typparameter T ersetzen und das wars.
Fast. Man muss schon noch angeben, welchen Typen man bei der Verwendung der generischen Klasse haben möchte. Das geschieht bei der Deklaration der Variablen. In deiner main(): LinkedList<Student>, was eine LinkedList für Studenten darstellt.
 
X

xlChaos

LinkedList<Student> studenten = new LinkedList<>();

Deine Version entspricht im Prinzip LinkedList<Object> studenten = new LinkedList<>();

So ganz hab ich die Aufgabe nicht verstanden. Sollt ihr die Klasse mit der main() jetzt anpassen oder soll sie unverändert bleiben?

Edit: Ach so, und was das class TestLinkedList<T> soll erschließt sich mir nicht. Ist das "ich schreib einfach mal überall <T> hin und schau was passiert", oder wie?
Hi, danke schon mal für deine Antwort. Wir sollten die Node und die LinkedList Klasse mit den Typparameter "befüllen", damit man quasi nicht mehr Studentenobjekte erzeugen muss sondern einfach die Generics nutzen kann.


Zu der Frage warum ich TestLinkedList<T> schreibe kann ich dir keine Antwort geben :D Ich habe es glaube noch nicht ganz verstanden, wann und wo man <T>oder einfach T schreibt...

Und mein eigentliches Problem und Frage ist, ob ich überhaupt einen Typparameter brauche in der main und wenn ja, wie ich das denn umsetzen soll ohne Fehler. Sobald ich <T> oder T schreibe kommen immer Fehlermeldungen. Wenn ich nichts schreibe, will eclipse nur, dass ich die beiden "studenten" LinkedLists Typecaste...
 
Zuletzt bearbeitet:
X

xlChaos

Hier mal meine Node Klasse:


Java:
public class Node<T> {
   
    private T data;
    private Node<T> next = null;
   
    public Node (T data) {
        this.data = data;
        this.next = null;
    }
   
    public Node<T> getNext() {
        return next;
    }
   
    public void setNext (Node<T> next) {
        this.next = next;
    }
    public T getData( ) {
        return this.data;
    }
   
    public void setData (T data) {
        this.data = data;
    }
}
Warum soll hinter jedem "Node" ein <T> stehen ? Eclipse zeig mir das nicht als Fehler an, aber es wird gelb angemakert wenn da kein <T> steht... Funktionieren tut es trotzdem
 
L

LimDul

Also, was man sich zu Generics merken muss:
* Generics existieren nur zur Compile-Zeit. Zur Laufzeit existieren die nicht.

Das heißt, folgende drei Listen sind zur Laufzeit quasi identisch:

Code:
List<Object> list1;
List<Student> list2;
List<RandomKlasse> list3;
List list4;
Wenn man sich das merkt, werden manche Dinge verständlich.

Wofür nutzt man Generics? Man möchte sicherstellen, dass mehrere Parameter/Rückgabewerte den gleichen Typ haben. Beispiel bei der Liste, man möchte das die get Methode den gleichen Typ zurückliefert, den die add Methode als Eingabe erlaubt. Man kann aber gleichzeitig nicht den Typ schon fest vorgeben - weil das macht erst der Nutzer der Liste. Vor Generics war es so, dass Typ zwangsweise fest vorgeben Object war. Damit konnte man alle Objekte reinstecken - man konnte es aber nicht einschränken.

Mit Generics kannst du nun sicherstellen, dass du den Typ einschränken kannst und der Compiler prüft das (zur Laufzeit kommt wieder die gleiche Liste wie früher raus, die in Wirklichkeit Objekte vom Typ Objekt verwaltet).

Bzgl. deiner Frage "Warum soll hinter jedem Node der Generics-Typ-parameter stehen?" Nun du sagst "Das Datenobjekt von meiner Node ist durch den Generics-Parameter T beschrieben". Das heißt der Nutzer erstellt z.b.
Java:
Node<String> myNode = new Node<>("Daten");
Wenn du nun auf der myNode.getNext aufrufst, bekommst du wieder ein Node Objekt zurück. Wenn du das ohne Typ-Parameter machst, dann hat dieses Node Objekt quasi als Datentyp "Objekt". Wenn du also getData auf dieser Node aufrufen würdest, würde ein Objekt vom Typ Objekt zurückommen und kein String. Das willst du mit Sicherheit nicht, weswegen du als Rückgabe von getNext Node<T> definierst.

Da Generics nur zur Compile-Zeit existierten, kannst du alle Klassen auch ohne Generics verwenden (Was im Endeffekt dem entspricht, wenn du Objekt als Generics Parameter reinsteckst). Allerdings will man das in 99% der Fälle nicht, weswegen der Compiler sagt "Die Klasse erwartet ein Generic, aber du verwendest es ohne - das ist zu 99% falsch.
 
Thema: 

Wie Generics richtig benutzen ?

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben