# Methoden wo der Parameter- und Rückgabetyp noch nicht fest steht.



## matze86 (9. Dez 2021)

Ich bin dabei, einen Code zu vereinfachen, kompakter zu machen. Ich habe 4 gleiche Methoden, die sich nur im Parameter unterscheiden, --- soweit so gut. 
Nur in den Methoden selbst steht fast der gleiche Code, nur mit unterschiedlichen Datentypen (int, float, double,String).

Jetzt möchte ich eine Methode erstellen, der die Anweisungen zusammenfasst, nur ich weiß nicht wie, weil man ja nicht weiß welcher Datentyp gerade abgerufen wird.

Wie kann man eine Methode erstellen, wo man im Parameter einen x-beliebigen Datentyp deklarieren kann und auch der Rückgabetyp x-beliebig sein kann?


----------



## httpdigest (9. Dez 2021)

Angenommen, du hast die Funktion (Pseudocode):

```
func Add(x, y) {
  return x + y;
}
```
Und x und y können mal zwei int, mal zwei float oder auch zwei Strings sein, dann musst du das als separate Methoden ausprogrammieren.
Es gibt zwar Überladung in Java, aber keine dynamischen Operatoren (wie etwa bei JavaScript). Bei Anwendung eines Operators muss statisch feststehen, welche konkreten Typen die Argumente haben.


----------



## matze86 (9. Dez 2021)

OK, na gut die Funktions-Methode hatten wir noch noch nicht. Ich zeig mal den Code vielleicht hat einer einen Vorschlag, wie man das kompakter gestalten kann, wie gesagt, möchte nichts fertiges sondern nur Tipps wo man was besser/kompakter definieren kann.


```
public static boolean abgebrochen;
            
            private static String lesen(String text) {
                String eingabeTemp;
                eingabeTemp = JOptionPane.showInputDialog("Bitte geben Sie einen " + text + " Wert ein:");
                
                if (eingabeTemp == null)
                    abgebrochen = true;
                else
                    abgebrochen = false;

                return (eingabeTemp);
            }
            private int bearbeiten(int x) {
                return x;
            }
            
            public static int einlesen(int wert) {
                int wertTemp = 0;
                boolean gelungen = false;
                String eingabeTemp;
                while (gelungen == false) {
                    eingabeTemp = lesen("int");
                    if (abgebrochen == false) {
                        try {
                            wertTemp = Integer.parseInt(eingabeTemp);
                            gelungen = true;
                        }
                        catch (NumberFormatException e) {
                            JOptionPane.showMessageDialog(null,"Ihre Eingabe war nicht gÃ¼ltig. Bitte wiederholen...");
                        }
                    }
                    else
                        gelungen = true;
                }
                return wertTemp;
            }
            
            public static double einlesen(double wert) {
                double wertTemp = 0;
                boolean gelungen = false;
                String eingabeTemp;
                while (gelungen == false) {
                    eingabeTemp = lesen("double");
                    if (abgebrochen == false) {
                        try {
                            wertTemp = Double.parseDouble(eingabeTemp);
                            gelungen = true;
                        }
                        catch (NumberFormatException e) {
                            JOptionPane.showMessageDialog(null,"Ihre Eingabe war nicht gÃ¼ltig. Bitte wiederholen...");
                        }
                    }
                    else
                        gelungen = true;
                }
                return wertTemp;
            }
            
            
        }
```


----------



## Jw456 (9. Dez 2021)

wenn der kleinste Datentyp ein int ist lässt es sich ja in einen Double  casten.

Du könntest eine Methode mit einem double  schreiben und diese in den beiden „einlesen“ Methoden,  nach dem Casten aufrufen.

Den Teil der in beiden Methoden gleich ist kannst du ja wider in eine Methode auslagern und aufrufen.


----------



## matze86 (9. Dez 2021)

Ich habe das jetzt mal umgestaltet, sieht jetzt so aus:

```
public static boolean abgebrochen;
            
            private static String lesen(String text) {
                String eingabeTemp;
                eingabeTemp = JOptionPane.showInputDialog("Bitte geben Sie einen " + text + " Wert ein:");
                
                if (eingabeTemp == null)
                    abgebrochen = true;
                else
                    abgebrochen = false;

                return (eingabeTemp);
            }
            
            private static double neu(String x) {
                double wertTemp = 0;
                boolean gelungen = false;
                String eingabeTemp;
                while (gelungen == false) {
                    eingabeTemp = lesen(x);
                    if (abgebrochen == false) {
                        try {
                            wertTemp = Double.parseDouble(eingabeTemp);
                            gelungen = true;
                        }
                        catch (NumberFormatException e) {
                            JOptionPane.showMessageDialog(null,"Ihre Eingabe war nicht gÃ¼ltig. Bitte wiederholen...");
                        }
                    }
                    else
                        gelungen = true;
                }
                return wertTemp;
            }
            
            
            public static int einlesen(int wert) {
                int wertTemp = (int) neu("int");
                return wertTemp;
            }
            
            public static double einlesen(double wert) {
                double wertTemp = neu("double");
                return wertTemp;
            }
```


----------



## Robert Zenz (9. Dez 2021)

Du kannst den Wert direkt retournieren, ohne die Zwischenvariable.

Ich habe hier allerdings bedenken wenn es darum geht `double` zu lesen und dann auf daraus einen `int` zu casten. Das funktioniert, ja, riecht aber nach Problemen am Ende des Tages (ich vertraue Gleitkommazahlen nur soweit wie ich sie zaehlen kann). Ein anderer Ansatz waere eine "Converter"-Methode zu verwenden und die Objekt-Varianten zu nutzen. In etwa so:


```
private static <WERT_TYP> WERT_TYP neu(String eingabeText, Function<String, WERT_TYP> converter) {
    WERT_TYP wert = null;
 
    while (wert == null) {
        String eingabe = lesen(eingabeText);
        wert = converter.apply(eingabe);
    }
 
    return wert;
}
```

Dann kann man das ganze so aufrufen (etwas zerlegt damit es leichter zu lesen ist, kann man auch alles auf eine Zeile packen):


```
private static int intEinlesen() {
    Function<String, Integer> converter = (eingabe) -> Integer.valueOf(Integer.parseInt(eingabe));
    Integer gelesenerWert = neu("int", converter);
    return gelesenerWert.intValue();
}

private static double doubleEinlesen() {
    Function<String, Double> converter = (eingabe) -> Double.valueOf(Double.parseInt(eingabe));
    Integer gelesenerWert = neu("double", converter);
    return gelesenerWert.doubleValue();
}
```

Fehlt natuerlich die Handhabung von Ausnahmen, aber vom Prinzip her.

Oder mit Methodenreferenzen statt Lambdas, was schoener waere meiner Meinung nach (macht auch Ausnahmen besser einfuegbar):


```
private static int intEinlesen() {
    return neu("int", DeineKlasse::convertToInteger).intValue();
}

private static double doubleEinlesen() {
    return neu("double", DeineKlasse::convertToDouble).doubleValue();
}

private static Integer convertToInteger(String eingabe) {
    return Integer.valueOf(Integer.parseInt(eingabe));
}

private static Double convertToDouble(String eingabe) {
    return Double.valueOf(Double.parseDouble(eingabe));
}
```


----------



## matze86 (9. Dez 2021)

Danke für die Ausführliche Antwort, aber mit den Beispielen kann ich (noch) nichts anfangen, gerade mit der ersten Variante. 
`private static <WERT_TYP> WERT_TYP neu...`


----------



## Robert Zenz (9. Dez 2021)

Das sind Generic-Types, also quasi Platzhalter fuer die eigentlichen Typen. Klassischerweise begegnest du diesen zuerst bei der `List`.


```
List<String> stringValues = new ArrayList<>();
```

Die `List` kann ja alle moeglichen Objekte halten, und als generischen Typ kann man eben den "eigentlichen" Typ der Objekte angeben. Der Vorteil ist dass man dann nicht wissen muss welche Typen es wirklich sind in den Methoden ("neu" muss das zum Beispiel nicht wissen), aber man erhaelt dennoch Typ-Sicherheit. Um mein Beispiel aufzugreifen, du kannst nicht sagen:


```
Integer gelesenerInteger = neu("double", DeineKlasse::convertToDouble);
```

Das wird einen Fehler werfen weil die Typen vom "converter" Parameter (`Double`) nicht mit dem zuweisenden Typen (`Integer`) uebereinstimmt.

Normalerweise werden die immer nur mit einem Buchstaben benannt, klassich "T", "K", "V" oder "E". Ich mag es richtige Namen zu verwenden, liest sich einfach besser.


----------



## 2Fast4Me (9. Dez 2021)

Ich bin Anfänger.

Wenn es nur um Zahlen geht, hilft vielleicht der Typ Number statt int und double.


----------

