# Generics



## Grombaner (26. Jul 2017)

Hallo zusammen,

es mag für viele eine Einfache Ausfgabe sein, aber ich stehe gedanklich so auf dem Schlauch, dass ich eine Lösung benötige:

Die Aufgabe ist: 
Implementieren sie im vorhandenen Projekt die fehlende Methode, sodass folgendes ausgegeben wir:
Hallo ist vom Typ java.lang.String
2.3 ist vom Typ java.lang.Float
a ist vom Typ java.lang.Character

public class GenericsAufgabe<T> {



   public <T, U, V> void spezialmethode(T t,U u, V v){

       System.out.println(t + " ist vom Typ " + t.getClass().getName());
       System.out.println(u + " ist vom Typ" + u.getClass().getName());
       System.out.println(v + " ist vom Typ" + v.getClass().getName());



   }



   public static void main(String[] args) {
       GenericsAufgabe  g = new GenericsAufgabe();

        String s = g.spezialmethode("Hallo");
        float f = g.spezialmethode(2.3f);
        char c = g.spezialmethode('a');

   }



Bei den Methoden in der main wird bemänglet, dass meine spezialmethode (Object, Object, Object) nicht mit der spezialmethode in der Main mit String,Float,usw. zusammenpasst..

Ich weiiß das ist bestimmt eine einfache Aufgabe, dennoch komme ich gerade nicht drauf. Kann mir jemand dabei helfen?

Viele Grüße !

Grombaner


----------



## Java20134 (26. Jul 2017)

Das Erste wäre, dass du in deiner Klassendefinition ein Generic hast, denn du aber eigentlich gar nicht benötigst und auch nicht initialisiert hast. Die Methode meldet einen Fehler, da du sie mit 3 Parametern in der Klasse beschrieben hast, aber nur einen Parameter in der main Methode übergibst.


----------



## Blender3D (26. Jul 2017)

```
public class GenericsAufgabe<T> {

    public T spezialmethode(T t) {
        System.out.println(t + " ist vom Typ " + t.getClass().getName());
        return t;
    }

    public static void main(String[] args) {
        GenericsAufgabe<String> str = new GenericsAufgabe<String>();
        GenericsAufgabe<Float> fl = new GenericsAufgabe<Float>();
        GenericsAufgabe<Character> ch = new GenericsAufgabe<Character>();

        String s = str.spezialmethode("Hallo");
        float f = fl.spezialmethode(2.3f);
        char c = ch.spezialmethode('a');

    }
}
```
Du musst den Typ deiner generische Klasse festlegen.
Siehe Codebeispiel.
Die Rüchgabe macht in Deinem Beispiel auch keinen wirklichen Sinn. Du solltest zuerst einmal den Sinn einer herkömmlichen Methode verstehen, bevor Du mit generischen Methoden anfängst.


----------



## Grombaner (26. Jul 2017)

Also Generic aus Klassendefinition nehmen
Die 2 anderen Paramer aus der Methode nehmen

Dann steht in der main noch can not convert from void to String/float/double und das ist der Punkt den ich nicht verstehe: sollte das T t nicht für einen beliebigen Typ stehen und dann fesstellen welchen Typ der Parameter in spezialmethode hat?


zur 2. Antwort:
Ich weiß nicht, ob ich das so machen darf, da die main von der Aufgabe vorgegeben war und ich nur die spezialmethode schreiben darf...

Vielen Dank für eure Antworten!


----------



## mrBrown (26. Jul 2017)

Blender3D hat gesagt.:


> Die Rüchgabe macht in Deinem Beispiel auch keinen wirklichen Sinn. Du solltest zuerst einmal den Sinn einer herkömmlichen Methode verstehen, bevor Du mit generischen Methoden anfängst.


Der Rückgabetyp ist void, warum sollte das keinen Sinn haben?




Grombaner hat gesagt.:


> Dann steht in der main noch can not convert from void to String/float/double und das ist der Punkt den ich nicht verstehe: sollte das T t nicht für einen beliebigen Typ stehen und dann fesstellen welchen Typ der Parameter in spezialmethode hat?


Deine Methode gibt void zurück, und das versucht du einem String/float/double zuzuweisen, was logischerweise nicht klappt 



Grombaner hat gesagt.:


> ich weiß eben nicht, ob ich den unteren Teil so abändern darf, die Aufgabenstellung besagt nur, dass ich die spezialmethode schreiben soll, der Rest war so vorgegeben...


Was genau war denn vorgegeben?


----------



## Grombaner (26. Jul 2017)

public static void main(String[] args) {
GenericsAufgabe g = new GenericsAufgabe();

String s = g.spezialmethode("Hallo");
float f = g.spezialmethode(2.3f);
char c = g.spezialmethode('a');

}


Die Klasse und die oben geschriebene main ist vorgegeben.

Ich soll die Methode spezialmethode schreiben, die am Ende ausgibt von welchem Typ die Parameter der spezialmethode in der main haben.


----------



## mrBrown (26. Jul 2017)

Dann fang noch mal ganz von vorne an 

Was für einen Typ muss den der Parameter von `spezialmethode` haben?


----------



## Grombaner (26. Jul 2017)

ich hätte jetzt gesagt den Typparameter T damit er später die verschiedenen Typen Strin/Float/Character annehmen kann


----------



## mrBrown (26. Jul 2017)

Soweit richtig  Reicht denn ein parameter?

Und was muss dann der Rückgabetyp sein?


----------



## Blender3D (26. Jul 2017)

mrBrown hat gesagt.:


> Der Rückgabetyp ist void, warum sollte das keinen Sinn haben?


[


Grombaner hat gesagt.:


> String s = g.spezialmethode("Hallo");
> float f = g.spezialmethode(2.3f);
> char c = g.spezialmethode('a');


Der Aufruf in seinem Code erwartet eine Rückgabe. Siehe oben.


----------



## Grombaner (26. Jul 2017)

mrBrown hat gesagt.:


> Soweit richtig  Reicht denn ein parameter?
> 
> Und was muss dann der Rückgabetyp sein?



Da ich 3 verschiedene typen habe würde ich sagen ich brauche 3 also T,U,V


----------



## mrBrown (26. Jul 2017)

Grombaner hat gesagt.:


> Da ich 3 verschiedene typen habe würde ich sagen ich brauche 3 also T,U,V


Wie viele Argumente werden denn in den Aufrufen jeweils übergeben, und wie viele verschiedene Typen gibt es pro Aufruf?


----------



## Grombaner (26. Jul 2017)

mrBrown hat gesagt.:


> Wie viele Argumente werden denn in den Aufrufen jeweils übergeben, und wie viele verschiedene Typen gibt es pro Aufruf?



1 Typ pro Aufruf und 1 Argument, also nicht 3 sondern 1 , das war der selbe Denkfehler wie vorhin...


----------



## mrBrown (26. Jul 2017)

Richtig 

Und was muss der Rückgabetyp sein?


----------



## Blender3D (26. Jul 2017)

mrBrown hat gesagt.:


> Und was muss der Rückgabetyp sein?


Da sich der übergeben Typ nur ausgibt, wäre keine Rückgabe logisch.
Funktion: int ergebnis = add( int a, int b   ){ return a+b; }
Eine Rückgabe ist nur dann sinnvoll, wenn der Input einen neuen Output auslösen soll.


----------



## Grombaner (26. Jul 2017)

auch T , sonst funktioniert es nur für eines der Beispiel und wenn ich void lasse bekomme ich wieder den selben convert Fehler


----------



## mrBrown (26. Jul 2017)

Blender3D hat gesagt.:


> Da sich der übergeben Typ nur ausgibt, wäre keine Rückgabe logisch.
> Funktion: int ergebnis = add( int a, int b ){ return a+b; }
> Eine Rückgabe ist nur dann sinnvoll, wenn der Input einen neuen Output auslösen soll.


Da die Aufgabenstellung einen Rückgabetyp fordert, muss es auch einen geben


----------



## mrBrown (26. Jul 2017)

Grombaner hat gesagt.:


> auch T , sonst funktioniert es nur für eines der Beispiel und wenn ich void lasse bekomme ich wieder den selben convert Fehler


Ja, T ist richtig 

Und wenn du dann jetzt Parameter und Rückgabetyp weißt, wie muss dann die Funktion aussehen?


----------



## Grombaner (26. Jul 2017)

public T spezialmethode(T t){

       System.out.println(t + " ist vom Typ " + t.getClass().getName());
       return t;
   }


----------



## Blender3D (26. Jul 2017)

Blender3D hat gesagt.:


> public T spezialmethode(T t) {
> System.out.println(t + " ist vom Typ " + t.getClass().getName());
> return t;
> }


Dann habe ich die Lösung bereits gepostet.
Und man sieht, dass Aufgaben nicht immer sinnvoll sind.
int gibZahlzurueck( int a ){ return a; }
int x = 1;
int y = gibZahlzurueck( x ):
kann man auch so lösen y = x;


----------



## mrBrown (26. Jul 2017)

Jetzt müsste deine Klasse generisch sein, was bei dieser Aufgabenstellung nicht klappt.
Du musst den generischen Typ noch extra angeben


----------



## mrBrown (26. Jul 2017)

Blender3D hat gesagt.:


> Dann habe ich die Lösung bereits gepostet.
> Und man sieht, dass Aufgaben nicht immer sinnvoll sind.
> int gibZahlzurueck( int a ){ return a; }
> int x = 1;
> ...


Bravo, du hast es jemandem ermöglicht, nicht selbst auf die Lösung zu kommen 

Und das Argument auch zurückgeben, oder zumindest den gleichen Typ zurückgeben, ist nicht sonderlich selten, guck zB mal in die Objects-Klasse^^


----------



## Grombaner (26. Jul 2017)

Richtig es klappt nicht und das ist eine orginal Klausuraufgabe und deshalb bin ich darüber verzweifelt, aber wenn die Aufgabenstellung schon keinen Sinn ergibt wenn man sonst nichts verändern darf dann bin ich nicht ganz so entäuscht von mir 

Danke für eure Hilfe!


----------



## mrBrown (26. Jul 2017)

Weißt du denn warum es nicht klappt und wie man das ändern kann?


----------



## Blender3D (26. Jul 2017)

mrBrown hat gesagt.:


> Und das Argument auch zurückgeben, oder zumindest den gleichen Typ zurückgeben, ist nicht sonderlich selten, guck zB mal in die Objects-Klasse^^


Object hat nur eine Methode mit Parameter und Rückgabewert.
boolean equals( Object o);
Die gibt zurück ob das übergeben Objekt und das Objekt selbst gleich sind. Das finde ich sinnvoll.


----------



## Grombaner (26. Jul 2017)

Ich nehme an es Klappt nicht , da in der main für jeden Typ eine lokale Variable angelegt wird, die von der Methode einen Rückgabewert in ihrem Typ erwartet... um das zu beheben muss ich 3 Instanzen der Klasse machen und ihnen mit <> ihren Typ übergeben

Bzw.

nehme ich die lokalen variablen raus, reicht auch eine Instanz der Klasse um das gewünscht auf der Konsole auszugeben


----------



## Meniskusschaden (26. Jul 2017)

Blender3D hat gesagt.:


> Object hat nur eine Methode mit Parameter und Rückgabewert.


@mrBrown hat sich nicht auf Object bezogen, sondern auf Objects.


Blender3D hat gesagt.:


> Eine Rückgabe ist nur dann sinnvoll, wenn der Input einen neuen Output auslösen soll.


Das kann z.B. sinnvoll sein, wenn man auf das übergebene (und zurück gegebene) Argument anschliessend direkt eine weitere Methode aufrufen möchte (oder dieselbe nochmal):`object.doThis().doThat();`.
Das wird zum Beispiel beim Decorator-Entwurfsmuster gerne gemacht.


----------



## Blender3D (27. Jul 2017)

Meniskusschaden hat gesagt.:


> Das kann z.B. sinnvoll sein, wenn man auf das übergebene (und zurück gegebene) Argument anschliessend direkt eine weitere Methode aufrufen möchte (oder dieselbe nochmal)bject.doThis().doThat();.
> Das wird zum Beispiel beim Decorator-Entwurfsmuster gerne gemacht.


Das stimmt, aber es macht halt keinen Sinn eine weitere Methode, auf eine Methode aufzurufen, wenn der übergebene Parameter unverändert durchgeschleust wird.
int unverändert( int x ){ return x; }
int add( int a, int b );
add( 1, unverändert(2) ) == add( 1, 2 );


----------



## Blender3D (27. Jul 2017)

Meniskusschaden hat gesagt.:


> @mrBrown hat sich nicht auf Object bezogen, sondern auf Objects.


Habe ich nicht genau gelesen.
Also meint er Methoden wie
public static <T> T requireNonNull(T obj);
Die gibt es unverändert zurück stimmt. Aber hier wird der übergebene Parameter auf null geprüft und eine Exception geworfen (Ist eine zentrale Anlaufstelle der Virtual Machine, um Nullpointerexceptions zu werfen).  Was man von obiger reinen Ausgabefunktion  nicht behaupten kann.


----------



## Meniskusschaden (27. Jul 2017)

Blender3D hat gesagt.:


> Das stimmt, aber es macht halt keinen Sinn eine weitere Methode, auf eine Methode aufzurufen, wenn der übergebene Parameter unverändert durchgeschleust wird.


Warum denn nicht? Einzelne Gegenbeispiele belegen doch nicht, dass es nie sinnvoll ist.


Blender3D hat gesagt.:


> Was man von obiger reinen Ausgabefunktion nicht behaupten kann.


Wir wissen ja nicht, wie die Methode später genutzt werden soll. Vielleicht ja so ähnlich, wie in diesem Beispiel:

```
objekt.druckeZusammenfassung().druckeDetails();
```
Das kann doch auch sinnvoll sein, wenn objekt durch keine der Methoden verändert wird.


----------



## Blender3D (27. Jul 2017)

Meniskusschaden hat gesagt.:


> objekt.druckeZusammenfassung().druckeDetails();


Das Beispiel hat keinen Übergabeparameter und gibt das Objekt selbst zurück.


Blender3D hat gesagt.:


> public T spezialmethode(T t) {
> System.out.println(t + " ist vom Typ " + t.getClass().getName());
> return t;
> }


Aber überlege Dir ob Du im obigen Beispiel einen Rückgabetype verwenden würdest.
Wenn ja, dann ist es wenigstens für Dich sinnvoll.


----------



## Meniskusschaden (27. Jul 2017)

Blender3D hat gesagt.:


> Das Beispiel hat keinen Übergabeparameter und gibt das Objekt selbst zurück.


Ach, hat er den Parameter zurückgegeben? Stimmt. Hm, dazu fällt mir auch keine sinnvolle Anwendung ein.


----------

