# Kleine Generics Aufgabe aus einer Prüfung... wie ist das gemeint?



## vandread (7. Feb 2013)

Hallo Leute,

ich schreib am Freitag eine Prüfung und bei den Übungen ist mir jetzt eine Aufgabe in die Finger gekommen wo ich erst mal 5 mal lesen musste um zu verstehen was der gute Professor da eigentlich will...

Um ehrlich zu sein bin ich mir nicht sicher was er da will 

Hier die Originale Aufgabe: https://dl.dropbox.com/u/14115692/Aufgabe.pdf

Aufgabentext:
*Die Klasse GenUtils enthält die Klassenmethode addAndDisplay(), die ein Objekt vom generischen Typen T zu einer Arraylist<T> hinzufügt. Anschließend wird der Inhalt der Liste ausgegeben. Programmieren Sie die Methode addAndDisplay() aus.

In main() der Klasse TestGenUtils, schreiben Sie bitte einen Aufruf der Klassenmethode addAndDisplay(), der einen Integer mit dem Wert 5 zu einer Arraylist hinzufügt (10 min)*

Soweit so gut... Ich möchte jetzt anmerken dass bei den Aufgaben immer platz gelassen wird wenn man irgendwo was ergänzen muss, auch oben bei den Klassennamen usw... (Siehe PDF)

Ich weiß nicht ob ich die Aufgabe richtig verstanden habe aber meine Lösung sieht wie folgt aus:


```
public class GenUtils<T> {

    public void addAndDisplay(T element, ArrayList<T> list) {
        list.add(element);

        for (T e : list) {
            System.out.println(e);
        }
    }
}
```


```
public class TestGenUtils {

    public static void main(String[] args) {
        ArrayList<Integer> myList = new ArrayList<>();

        GenUtils<Integer> gu = new GenUtils<>();

        gu.addAndDisplay(5, myList);
    }
}
```

Es gibt da nur ein Problem... oben bei "class GenUtils" wurde kein Platz gelassen um eine Typvariable reinzuschreiben, also muss wohl meine Lösung falsch sein... Außerdem finde ich das auch sehr komisch... Vielleicht denke ich ja auch nur falsch...
Außerdem ist in der Aufgabe nur von addAndDisplay() die rede als würde die Methode keine Übergabeparameter besitzen...

Deswegen wollte ich mal wissen was ihr dazu sagt...


----------



## JohannisderKaeufer (7. Feb 2013)

Es wird verlangt dass 
	
	
	
	





```
addAndDisplay()
```
 eine Klassenmethode ist. Das was du gemacht hast sind so gesehen Instanz-Methoden.

Das Schlüsselwort, dass verwendet werden soll heißt static.
Und static Methoden können auch Parametrisiert werden, allerdings nicht über die Klasse.


```
import java.util.*;

public class GenUtils {

  public static <T> void addAndDisplay(T element, Collection<T> list){
    list.add(element);
    for(T t:list){
      System.out.println(t);
    }
  }

}
```


```
import java.util.*;
public class TestGenUtils{

  public static void main(String[] args){
    List<Integer> list = new ArrayList<>();
    GenUtils.addAndDisplay(5, list);
  }
}
```

Statt die Interface Collection und List, gutem Programmierstil entsprechend, kann man der Aufgabenstellung entsprechend auch direkt gegen ArrayList programmieren.

In der Aufgabenstellung wird auch von main(), anstatt wie vorgegeben main(String[] args) geschrieben, deshalb gehe ich davon aus, daß bei addAndDisplay() auch die Argumente weggelassen wurden, um Konsistent zu bleiben.


----------



## Landei (7. Feb 2013)

Die Lösung ist korrekt, aber...



JohannisderKaeufer hat gesagt.:


> Es wird verlangt dass
> 
> 
> 
> ...



So weit so gut, aber das geht genauso mit nicht-statischen Methoden.

Es ist verwirrend zu sagen, dass eine Methode "über die Klasse parametrisiert" wird. Entweder _die Klasse_ ist parametrisiert (dann können die entsprechenden Parameter auch von der (nicht-statischen) Methode benutzt werden), oder _die Methode_ selbst ist parametrisiert, oder beides.


----------



## DerFeivel (7. Feb 2013)

Eine Methode die zwei (völlig verschiedene) Dinge tut?


Und sowas wird gelehrt?


----------



## vandread (7. Feb 2013)

Vielen Dank für die Hilfe! 

Nur eine kleine Frage...



> Und static Methoden können auch Parametrisiert werden, allerdings nicht über die Klasse.



Wie darf ich das Verstehen?
Also ein kleines Beispiel...


```
public class Foo {
 
  public static <T> T bla(T val){
    return val;
    }
  }
 
}
```

Das geht so okay...
Die Methode ist static und wurde selber parametrisiert...

Was aber wenn ich sowas hier mache?


```
public class Foo <T> {

 public void bla(T val){
    System.out.println(T);
    }
  }

  public static <T> T bla(T val){
    return val;
    }
  }
 
}
```

Das dürfte ja nach deiner Aussage nicht gehen...
Logisch kann ich mir das nur so erklären dass wenn ich noch keine Instanzerzeugt habe die static Methode gar nicht wissen kann für das T steht... daher müsste es wohl so aussehen:


```
public class Foo <T>{

 public void bla(T val){
    System.out.println(T);
    }
  }

  public static <X> X bla(X val){
    return val;
    }
  }
 
}
```

Die Parameter müssen unterschiedlich sein?!


----------



## KSG9|sebastian (7. Feb 2013)

```
class My<A> {

   // verwendet das A aus der Klasse
   public A getA(){ return null; }

   // ein "neues" A wird definiert, dieses neue A entspricht NICHT dem A der Klasse/des Objekts
   // Die IDE meldet auch als Warning: "the parameter type A is hiding the type A"
   public <A> A getAnother(){ return null; }
}
```

Der Code sollte es erklären.


----------



## Landei (7. Feb 2013)

vandread hat gesagt.:


> Was aber wenn ich sowas hier mache?
> 
> 
> ```
> ...



Doch, nur ist das T, das die Methode verwendet, ein anderes als das der Instanz. Allerdings vermute ich, dass der Compiler meckert, weil die beiten Ts dieselbe Erasure [c]Object[/c] haben, und damit die beiden Methoden [c]bla[/c] ins Gehege kommen. Müsste man mal ausprobieren. Aber wenn die Methoden unterschiedlich heißen, sollte es auf jeden Fall gehen.



> Logisch kann ich mir das nur so erklären dass wenn ich noch keine Instanzerzeugt habe die static Methode gar nicht wissen kann für das T steht... daher müsste es wohl so aussehen:
> 
> 
> ```
> ...



Nein, müssen sie nicht. Wie gesagt weiß ich jetzt aus dem Hut nicht genau, ob eine der beiden Methoden umbenannt werden müsste, aber prinzipiell kannst du ein "Klassen-T" und ein völlig unabhängiges "Methoden-T" haben. Selbst _ohne_

```
static
```
 würde das funktionieren:


```
public class Foo <T>{

 public void bla1(T val){
    System.out.println(T);
    }
  }

  public <T> T bla2(T val){
      return val;
    }
  }
 
}
```

Ob das eine gute Idee ist, sein einmal dahingestellt.


----------

