Mit Methoden kann man definieren für was <T> steht. Geht das auch irgendwie für Variablen?

sirbender

Top Contributor
Im Code Schnipsel unten kann ich eine statische Methode erstellen, die mir erlaubt alle möglichen Collection-Konstruktor-Referenzen zu übergeben und ich bekomme direkt ein Objekt vom selben Typ zurück ohne Casting. Also ArrayList::new gibt mir ArrayList<String> zurück ohne Compilererror.

Gibt es eine Möglichkeit die Variable supplier so zu definieren, dass sie auch alle möglichen Collection-Konstruktor-Referenzen akzeptiert und mir dann auch den entsprechenden Typ zurückgibt - identisch mit der statischen Methode. Die statische Methode erlaubt es zu definieren, also z.B. <T> und auch sowas wie DEST mit DEST extends Collection<T>. Geht sowas auch irgendwie mit Variablen?

Supplier<T, ? extends Collection<T>> supplier = // akzeptiert ArrayList<String>::new, LinkedList<String>::new, etc.

Sowas wie <T, DEST extends Collection<T>> Supplier<DEST> supplier = ArrayList<String>::new; geht ja auch jeden Fall nicht.

Kann man diese Art von Definition nur bei Methoden machen und nicht bei Klassen, Variablen, etc.?

package incubator;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;

public class MethodReferenceTest {

public static void main(String[] args) {

String[] array = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" };
List<String> list = Arrays.asList(array);
ArrayList<String> result = transferElements(list, ArrayList::new);

Supplier<ArrayList<String>> supplier = ArrayList<String>::new;
ArrayList<String> get = supplier.get();
}

public static <T, SOURCE extends Collection<T>, DEST extends Collection<T>> DEST transferElements(SOURCE sourceCollection, Supplier<DEST> collectionFactory) {
DEST result = collectionFactory.get();
for (T t : sourceCollection) result.add(t);
return result;
}
}
 

Marinek

Bekanntes Mitglied
Kurze Antwort: Nein das geht nicht. Die generics werden zur Laufzeit aus dem Quellcode entfernt.

Lange Antwort: du benötigst eine callback Funktion, die das passende Objekt liefert.
 

Neumi5694

Top Contributor
Jein ... es gibt was Besseres.
Seit einigen Versionen kannst du mit dem Schlüsselwort var arbeiten.
Vorteil: Die gesamte Definition der Variable steht RECHTS von der Zuweisung.
Nachteil: Du musst wissen, was du tust. Änderst du die Quelle der Daten, so ändert sich der Typ der Variable und alle späteren Aufrufe könnten dann Compilerfehler auslösen.

Java:
//Alt
String result = new Supplier<String>{/*Hier MUSS ein String geliefert werden, da die Variable den Typ String hat*/}.get();
//Neu
var result = new Supplier<>{/*Hier wird ein eindeutiger Datentyp geliefert, die Variable kriegt den gleichen Typ*/}.get();
 

sirbender

Top Contributor
Kurze Antwort: Nein das geht nicht. Die generics werden zur Laufzeit aus dem Quellcode entfernt.

Lange Antwort: du benötigst eine callback Funktion, die das passende Objekt liefert.
Hmm. Die statische Methode gibt aber trotzdem korrekt ArrayList<String> zurück - zumindest meckert der Compiler nicht, wenn man folgendes schreibt: ArrayList<String> result = transferElements(list, ArrayList::new);

Das Argument ArrayList:new ist noch nicht mal typisiert. Und trotzdem schafft es der Kompiler irgendwie zu erkennen, dass 'result' vom Typ ArrayList<String> ist.

Ich weiss schon irgendwie was du meinst. Er checkt zur Kompilierzeit, dass alles korrekt ist und am Ende steht da nur noch eine ArrayList result;

Trotzdem sehr verwirrend, dass der Compiler, das nicht auch bei der Variablen-Definition irgendwie zulässt. Die nötige Info das durchzulassen wäre ja genauso möglich wie bei Methoden. Hat man das nicht erlaubt, weil dann die Syntax von Java noch komplizierter geworden wäre?

Ich muss schon sagen, wer heute mit Java started hat ganz schön viel an Syntax zu lernen um jeden Sourcecode bis Java17 problemlos lesen zu können.
 

sirbender

Top Contributor
Jein ... es gibt was Besseres.
Seit einigen Versionen kannst du mit dem Schlüsselwort var arbeiten.
Vorteil: Die gesamte Definition der Variable steht RECHTS von der Zuweisung.
Nachteil: Du musst wissen, was du tust. Änderst du die Quelle der Daten, so ändert sich der Typ der Variable und alle späteren Aufrufe könnten dann Compilerfehler auslösen.

Java:
//Alt
String result = new Supplier<String>{/*Hier MUSS ein String geliefert werden, da die Variable den Typ String hat*/}.get();
//Neu
var result = new Supplier<>{/*Hier wird ein eindeutiger Datentyp geliefert, die Variable kriegt den gleichen Typ*/}.get();
Guter Tip. Ich sitze noch bei Java8 fest, aber ich werde es mir mal anschauen.
 

Neumi5694

Top Contributor
Das Argument ArrayList:new ist noch nicht mal typisiert. Und trotzdem schafft es der Kompiler irgendwie zu erkennen, dass 'result' vom Typ ArrayList<String> ist.
Das hat folgenden Grund. Es gibt eigentlich keine ArrayLists eines bestimmten Typs, also ArrayList<String>
ArrayList<Object> und ArrayList<String> sind identisch, dazwischen besteht kein Unterschied.

Die Generics sind dazu da, um dir beim Programmieren zu helfen, sonst müsstest du ständig hin- und hercasten. Außerdem können so offensichtliche Zuweisungsfehler vermieden werden.

"ArrayList::new" entspricht "() -> new ArrayList<>()".
Die Verwendung von ArrayList::new funktioniert also grundsätzlich immer, der Rest des Aufrufs muss halt zusammenpassen.
 
Zuletzt bearbeitet:

Neumi5694

Top Contributor
Nur der Vollständigkeit halber:
Das hier funktioniert in Java durchaus
Java:
HashMap<String, List<?>> variable = ...;
//oder auch
HashMap<String, Collection<T>> variable =...;
//sofern T vorher definiert wurde.
 

KonradN

Super-Moderator
Mitarbeiter
Wenn man sich überlegt, was denn der Sinn hinter Generics ist, dann ist klar, dass dies nur Sinn macht bei Dingen, die universell von außen nutzbar sind. Dies ist bei Klassen oder Methoden möglich. Das Beispiel ArrayList ist ja genannt worden und man will halt eine ArrayList für bestimmte Elemente haben.

Das ist in sofern wichtig, als das man hier noch nicht wissen kann, was da später gespeichert werden soll. Und unter dem Strich wird es am Ende ein universeller Typ wie Object (oder eben etwas anderes, wenn das Generic spezifiziert wurde).

Bei einer Variablen, die nur intern verwendet wird, macht dies einfach keinen Sinn. Wenn Du da eine beliebige Referenz speichern können willst, dann nimmst Du halt Object. Wenn da das gewünschte etwas wäre wie ein T extends Comparable<T> dann wäre die Variable einfach ein Comparable. Du würdest da schlicht nichts gewinnen, wenn da auch irgendwelche Generics möglich wären.

Das var Schlüsselwort geht da auch in eine ganz andere Richtung. Und ich würde dringend davon abraten, dies nicht zu sehr zu nutzen. Hintergrund ist hier einfach, dass dies keine funktionelle Erweiterung ist und Dir somit eine neue tolle Funktionalität bietet wie Generics. Statt dessen führt es leicht dazu, dass Typen verschleiert werden und dann im Nachhinein Probleme auftauchen. Ein einfaches kleines Beispiel:

Java:
var myList = new ArrayList<String>();
wäre eine gültige Syntax in Java. Dies ist gleichbedeutend zu

Java:
ArrayList<String> myList = new ArrayList<String>();
(wobei das zweite <String> optional ist und eher nur <> geschrieben wird.)

Das Problem kommt, wenn dieser Variable im Anschluss neue Listen zugewiesen werden sollen. Man ist halt auf genau diese ArrayList angewiesen. In der objektorientierten Softwareentwicklung gibt es eine kleine Regel: Man soll gegen Interfaces entwickeln. Daher wäre hier halt als Code sinnvoll:
Java:
List<String> myList = new ArrayList<String>();

Damit kann ich myList nun beliebige Implementationen von List zuweisen in Ihrem Gültigkeitsbereich.

Das einfach nur einmal als Anregung um hier nicht in irgendwas hinein zu stolpern, das "cool" aussieht und dann später ggf. zu Problemen führt. Aber ehe da ein Aufschrei kommt: Es spricht nichts gegen die Verwendung von var wenn man sauber entwickelt. Dann kann es ein super Weg sein, um Code kürzer zu schreiben. Und wenn man sauber entwickelt, dann sind die Methoden kurz und übersichtlich und einer Variablen wird nichts neues zugewiesen das ein anderen Typ haben könnte. Und wenn, ist es so übersichtlich, dass es einfach zu beheben ist.
Meine Empfehlung richtet sich also speziell an Anfänger, die hier eben eher weniger auf Clean Code achten. Und wo dieses Entwickeln gegen Interfaces etwas ist, das diese noch bewusst machen sollten - incl. der Nennung des Interfaces!

Aber das ist einfach nur meine Sichtweise.
 

Neumi5694

Top Contributor
Falls man innerhalb des selben Blocks (und nur dort ist "var" gültig) nochmal was Anderes zuweisen will mit einem potentiell anderen Datentyp dann ist es natürlich notwendig, eine übergeordnete Klasse oder ein Interface anzugeben.
Ansonsten kann man damit hervorragend arbeiten.

Der Compilier macht aus dem hier:
Java:
var item = useLabel? new JLabel()  : new JButton();
auch ganz brav ein JComponent Objekt. Aus allen möglichen Rückgabewerten wird die erste gemeinsame übergeordnete Klasse ermittelt.
Was ich mal testen muss, wäre, ob er noch zusätzlich angegebene Interfaces erkennen würde.
also "JComponent implements Hassunichgesehen", falls die Klassen beider Rückgabewerte noch explizit dieses Interface implementieren würden.
 

volcanos

Bekanntes Mitglied
FloatArray<GENERICS> <T> mit 2 Nachkommastellen erzwingen !!!

Java:
import java.text.DecimalFormat;

public class DiverseExamples
{       
    public static<T> void printArrayFloat(T[] array)
    {
        for(T element : array)
        {
            // FloatArray mit 2 Nachkommastellen erzwingen !!!
            DecimalFormat df = new DecimalFormat("#####0.00");
            System.out.println(df.format(element));                 
        }       
        System.out.println();
    }
    
    
    // Main:
    public static void main(String[] args)
    {           
        Float[] floatArray = { 1.341000000f, 9.22888f, 1.044f, 17.500f, 220.5000f };
        
        // FloatArray mit 2 Nachkommastellen erzwingen !!!
        printArrayFloat(floatArray);
        
        // FloatArray mit 2 Nachkommastellen erzwingen !!!
        float number = 17.5000000f;
        String str = String.format("%.02f", number);       
        System.out.println(str);       
    }
}
 

httpdigest

Top Contributor
Verstehe nicht, was das mit irgendwas hier zu tun hat.
Dein Generic Typparameter ist völlig nutzlos und deine printArrayFloat Methode ist 100% äquivalent zu:
Java:
public static void printArrayFloat(Object[] array) {
  for (Object element : array) {
    // FloatArray mit 2 Nachkommastellen erzwingen !!!
    DecimalFormat df = new DecimalFormat("#####0.00");
    System.out.println(df.format(element));
  }
  System.out.println();
}
weil Java Arrays covariant sind, und du somit ein Float[] auch zu einem Object[] zuweisen kannst.
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
B Leere vererbte Interface-Methoden Allgemeine Java-Themen 8
R Programm führt Methoden gleichzeitig aus Allgemeine Java-Themen 2
Encera Unterschied zweier "toString"-Methoden Allgemeine Java-Themen 1
torresbig Klasse mit extends Calendar über Methoden ändern (Hirnblockade) Allgemeine Java-Themen 7
Sachinbhatt Sind alle Methoden in Java implizit virtuell Allgemeine Java-Themen 2
B Arrays von Methoden möglich? Allgemeine Java-Themen 44
N abstracte klassen methoden Allgemeine Java-Themen 32
G Methoden für die Zukunft sinnvoll? Allgemeine Java-Themen 4
nonickatall Methoden Kann man Klassen/Methoden aus Variablen heraus aufrufen? Allgemeine Java-Themen 6
LimDul Hä? Lambda-Ausdruck geht, Methoden-Referenz nicht Allgemeine Java-Themen 8
B Methoden Java Getter und Setter Methoden Allgemeine Java-Themen 9
Y Java Methoden unterschiedliche Zahlenreihen Allgemeine Java-Themen 2
S Interface Design von HookUp oder Callback Methoden für eigenes Framework Allgemeine Java-Themen 9
F Sich automatisch aufrufende Java-Methoden Allgemeine Java-Themen 2
J Namen von Methoden über Reguläre Ausdrücke bearbeiten Allgemeine Java-Themen 6
D Methoden Methoden anpassen und fehlende Funktionen hinzufügen Allgemeine Java-Themen 475
V Threads Probleme beim Aufrufen von Methoden einer anderen Klasse (Threads) Allgemeine Java-Themen 14
R Statistische Methoden (Mathematik) Aufgabe Allgemeine Java-Themen 9
X Brüche kürzen mittels Methoden und ggT Allgemeine Java-Themen 15
L Operatoren Java Reflections: Alle Methoden einer Klasse aufrufen ohne Exceptions Allgemeine Java-Themen 5
L mehrere Methoden Allgemeine Java-Themen 19
KeexZDeveoper Zugriff auf Methoden vom Server Allgemeine Java-Themen 7
B StAX Parser - mehrere Methoden, ein XML Allgemeine Java-Themen 4
F Operationen/Methoden einen WebService im Browser mit Apache Axis aufrufen Allgemeine Java-Themen 4
A Automatisches Methoden Laufzeiten logging? Allgemeine Java-Themen 7
M Quellcode von Java-Methoden Allgemeine Java-Themen 9
rentasad Design-Frage - Interfaces, Klassen, statische Methoden Allgemeine Java-Themen 3
N HashMap und Methoden richtig einbinden Allgemeine Java-Themen 2
R Variable durch mehrere Methoden ändern und nutzen Allgemeine Java-Themen 17
Q-bert Methoden Methoden in Java Allgemeine Java-Themen 13
D Methoden Java-Aufgabe Allgemeine Java-Themen 2
M Compiler-Fehler Methoden-Referenz Allgemeine Java-Themen 5
X Threads Externe Variablen in Run Methoden verändern Allgemeine Java-Themen 4
S 2 methoden mit gleichen namen und ein Interface Allgemeine Java-Themen 9
F Enum-werte als Methoden-Parameter übergeben Allgemeine Java-Themen 6
N Vererbung Design-Problem mit vorhandenen, von der Klasse unabhängigen Methoden Allgemeine Java-Themen 12
E OOP Objekte und Methoden Allgemeine Java-Themen 1
K Java ruft Methoden nicht der Reihe nach auf Allgemeine Java-Themen 14
N Methoden Methoden einer Klasse auf Grundlage eines Strings aufrufen Allgemeine Java-Themen 6
T Java Array in Methoden Allgemeine Java-Themen 1
D Code für bereitgestellte Methoden Allgemeine Java-Themen 1
P Entity Objekt Methoden vs Service methoden Allgemeine Java-Themen 2
R Signatur von Methoden in eine Datei schreiben? Allgemeine Java-Themen 4
A Methoden verändern Allgemeine Java-Themen 12
F Methoden Arraylist weiterverwenden nach methoden Aufruf Allgemeine Java-Themen 2
J Best Practice Testen von protected Methoden Allgemeine Java-Themen 7
L Methoden "Schiffe versenken" Quellcode in Methoden umwandeln Allgemeine Java-Themen 6
G Matrix reduzieren zwei Methoden Allgemeine Java-Themen 2
Sogomn Best Practice "Doppelte" Methoden Allgemeine Java-Themen 3
Paul15 String Methoden Allgemeine Java-Themen 7
G Methoden BMI -Wert Aufgabe(Methoden) Allgemeine Java-Themen 4
F Testen von Methoden Allgemeine Java-Themen 3
S "Vererben" statischer Felder/Methoden Allgemeine Java-Themen 4
F Methoden in der Enumeration Klasse Allgemeine Java-Themen 1
S Methoden ohne Methodenkopf ?! Allgemeine Java-Themen 5
T Überschreiben von Methoden Allgemeine Java-Themen 6
M Methoden werden in falscher Reihenfolge bearbeitet Allgemeine Java-Themen 10
S Methoden Methoden überschreiben Allgemeine Java-Themen 3
N Threads statische Methoden in Threads Allgemeine Java-Themen 5
O Java-Obfuscator, welcher einzelne Methoden, Klassen und Ordnerstrukturen ausnehmen kann. Allgemeine Java-Themen 1
A also definition von klassen und string methoden und algorithmik Allgemeine Java-Themen 13
X Eigene Annotation - mit Bedingung für ganze Klassen oder Methoden Allgemeine Java-Themen 2
A Threads Lock über mehrere Abschnitte in verschiedenen Methoden Allgemeine Java-Themen 5
S Methoden Frage Allgemeine Java-Themen 2
R Wie kann man diese Methoden in arrays etablieren? Allgemeine Java-Themen 8
M Methoden in Rescources speichern Allgemeine Java-Themen 4
G Synchronisation nicht statischer Methoden Allgemeine Java-Themen 4
A Vererbung finale Methoden überschreiben Allgemeine Java-Themen 24
A Methoden parallelisieren? Allgemeine Java-Themen 2
L Methoden methoden an generischen klassentyp anpassen Allgemeine Java-Themen 5
C Methoden Übernahme von standart nativen Methoden? Allgemeine Java-Themen 9
B Zusammenfassen verschiedener ähnlicher Methoden Allgemeine Java-Themen 8
K JNI: Methoden aus unterschiedlichen Threads aufrufen Allgemeine Java-Themen 3
P Unterschiedliche Clone- Methoden Allgemeine Java-Themen 5
MQue Spezialfrage Überschreiben von Methoden Allgemeine Java-Themen 14
B Methoden Alle Methoden und Variablen aus Java-Dateien auslesen. Allgemeine Java-Themen 7
MiMa Rekursive Methoden Allgemeine Java-Themen 3
S Programm das alle aufgerufenen Methoden ausgibt..? Allgemeine Java-Themen 6
F ListIterator (next & previous methoden) Allgemeine Java-Themen 5
W Frage zu Refactoring statischer Methoden Allgemeine Java-Themen 4
M Methoden/Klassen für andere Projekte Allgemeine Java-Themen 4
T Methoden per String-Namen aufrufen Allgemeine Java-Themen 2
C Kapselung Warum graift man auf Variablen nur über Methoden und nich direkt zu? Allgemeine Java-Themen 10
M Methoden Static Methoden und Thread??? Allgemeine Java-Themen 4
A Methoden ohne Referenzen finden Allgemeine Java-Themen 9
turmaline OOP zwei gleiche Methoden mit kleinen Unterschieden Allgemeine Java-Themen 15
G JUnit Test Methoden in anderen Thread verlagern Allgemeine Java-Themen 4
K Auf Methoden der Runnable Klasse zugreifen Allgemeine Java-Themen 2
S Methoden Class.forName() >> Methoden - Reihenfolge Allgemeine Java-Themen 5
D Passende Name für Methoden finden Allgemeine Java-Themen 3
D Wann sollte ich statische Methoden und Variablen benutzen? Allgemeine Java-Themen 44
A Methoden laufen im Konstruktor, außerhalb allerdings nicht Allgemeine Java-Themen 2
M Generische Methoden mit Java und globale Variablen Allgemeine Java-Themen 9
GianaSisters ArrayList in Methoden übergeben Allgemeine Java-Themen 3
S static methoden Allgemeine Java-Themen 9
J coole Methoden Allgemeine Java-Themen 6
R Methoden in einem Thread unterschiedlich oft ausführen Allgemeine Java-Themen 4
A OOP: Überschreiben/Implementierung von Methoden Allgemeine Java-Themen 5
P Methoden und Werte Allgemeine Java-Themen 17
E Performace/Ausführungszeit von Methoden ermitteln Allgemeine Java-Themen 4

Ähnliche Java Themen

Neue Themen


Oben