Rückgabe von zwei Werten: String und double

Hallo zusammen,

ich habe eine Frage zu Rückgabewerten.
Ich würde gerne nicht nur ein Datentyp zurückgeben, sondern mind. 2.
Also als Beispiel einen Wert (int oder double und zusätzlich einen String).

Wie kann ich das denn machen und wie würde das genau aussehen?
Zum einen Methodenkopf und die Methode, und wie rufe ich dann wiederum die Methode auf und erhalte den Wert?

Klar, könnte ich eine Klasse dafür erstellen, aber gibt es hierfür von Hause aus auch schon etwas?

Dankeschön für die Hilfe
 
K

kneitzel

Also generell sollte man da dann tatsächlich über das Design nachdenken. Normalerweise bilden die Werte ein Objekt an sich. Also ein Preis besteht US dem eigentlichen Wert und der Währung. Somit der Art.
Oder es geht um einen bestimmten Teil eines Objekts und es geht um eine Veränderung an eben diesem Objekt, dann würde die Methode nichts zurück geben Sonden Instanzvariablen anpassen,

Man findet aber teilweise Tupel oder Pairs. In .Net sind diese ein fester Bestandteil und das ließe sich in Java auch einfach abbilden:
Java:
public class Tuple<X, Y> {
  public final X x;
  public final Y y;
  public Tuple(X x, Y y) {
    this.x = x;
    this.y = y;
  }
}
Aber das ist ein schlechtes Design, was am Beispiel mit dem Preis deutlich wird, So könnte man einen Preis auch mit Tupel<Double, String> abbilden, aber dann hat man x als Wert und y als Währung? Das ist im Code wenig intuitiv.

Und noch schlechter: man könnte auch ein Array von Object nehmen und da Werte speichern. Aber dann gibt man die Typsicherheit auf und dann hat man Wert in 0 und Währung in y - also auch nicht perfekt.

Die letzten zwei Lösungen sind nur angegeben um die reine Möglichkeit aufzuzeigen. Generell ist es in meinen Augen ein Zeichen eines schlechten Designs und daher keine gute Lösung,
 
Dir ist sicherlich bewusst dass Dir 'final' und großschreiben rein gar nichts bringt?


Klar, könnte ich eine Klasse dafür erstellen, aber gibt es hierfür von Hause aus auch schon etwas
Eine Methode kann immer nur einen Rückgabetyp besitzen. Dieser kann allerdings auch ein Array oder Klasse sein. Nimm einfach ein Array. Etwas Fertiges gibt es dafür nicht.
 
Dir ist sicherlich bewusst dass Dir 'final' und großschreiben rein gar nichts bringt?
final bringt natürlich was - der Compiler verhindert das Ändern des Felds (ob es mit Reflection geht, ist für diesen Fall völlig irrelevant).
Und Großschreibung ist Konvention für (nicht-primitive) Typen.

(Ein anderer Name bringt allerdings wirklich nichts)


Nimm einfach ein Array.
Nein, nimm kein Array. Array ist die schlechteste Wahl dabei.
 
Zuletzt bearbeitet:
K

kneitzel

Also Array ist besonders schlecht, da es um die Rückgabe von Werten mit unterschiedlichen Typen ging. Somit müsste man da dann ein Array von Object nehmen... Und damit hat man dann nicht mehr die Prüfung des Typs....

Und vom Design her ist dies auch bedenklich, denn es wird auf eine Kapselung von Daten verzichtet. Zu so einem Array braucht man ja noch weitere Detailinformationen: was steckt in 0 und was in 1? Und Rückgabe ist ein Array ... ein Array muss aber nicht Länge 2 haben. Somit gibt es Detail-Informationen außerhalb des Methodenkopfes.
Also hat man dann in der Klasse, die das Array zurück gibt, auch noch Konstanten für 0 und 1 a. la. PRICE_VALUE und PRICE_CURRENCY, aber das sind ja nicht wirklich Dinge, die zu der Klasse selbst gehören sondern zu der Rückgabe / dem Array...

Was den Vorschlag der Tupel Klasse angeht:
Hier kann man sich überlegen, was man wie braucht. Diese Variante ist speziell als Rückgabe-Typ konzipiert: Werte werden nur über den Konstruktor gesetzt, daher final. Statt Getter zu implementieren wurden die Felder hier einfach Public gesetzt. Das kann jeder so machen, wie er es möchte. Man kann auch mal schauen, wie das andere implementiert haben: Apache Commons hat meines Wissens auch so eine Klasse. Dort wurde das aber aufgebaut zu Pair, MuablePair und ImmutablePair. Felder sind nicht Public und Zugriff erfolgt über Getter. MutablePair hat auch Setter. Und es wird über Left/Right oder Key/Value zugegriffen statt x und y. So kann man das also aufblähen wenn man es benötigt, Und natürlich equals, compareTo, .... sind notwendig um es für eine Library universell nutzbar zu machen.

Aber meine Meinung dazu habe ich ja auch schon deutlich gemacht: ich halte nichts davon und sehe es eher als Zeichen schlechten Designs an. (Wobei es Ausnahmen geben kann, klar. Also ist dies eine stark vereinfachte Aussage, ähnlich wie der Hinweis an Anfänger, dass außer der main Methode nichts static sein soll.)
 
K

kneitzel

Ja eben. Deine nimmt aber alles an und das 'final' suggeriert eine immutabilität welche es nicht gibt.
Was meinst du mit ‚Meine nimmt alles an‘?

Und die Bedeutung von final ist klar und deutlich definiert:

‚Once a final variable has been assigned, it always contains the same value. If a final variable holds a reference to an object, then the state of the object may be changed by operations on the object, but the variable will always refer to the same object. This applies also to arrays, because arrays are objects; if a final variable holds a reference to an array, then the components of the array may be changed by operations on the array, but the variable will always refer to the same array‘

Und auch das Verständnis ist generell wichtig. Denn bei dem ImmutablePair gibt der Getter auch die Referenzen heraus. Wer also hier vermutet, dass sich dieses ‚Imutable‘ auf mehr als nur das Pair selbst bezieht, der irrt gewaltig.

Also ja: Wer kein Java kann, der mag Probleme haben, Code zu verstehen. Aber das sehe ich nicht zwingend als Fehler an, aber das würde bereits in vergangenen Threads zu Clean Code behandelt.

Aber klar: im Java Umfeld ist es unüblich, Public Felder zu nutzen, das sehe ich auch durchaus als Kritikpunkt. Hier kommt aber schlicht meine Schreibfaulheit auf dem Tablet zum tragen. (In der IDE hätte ich es tatsächlich anders gemacht, denn da ist es ein Tastendruck und ich habe Getter und/oder Setter für die Variable generiert.)
 
Ja eben. Deine nimmt aber alles an und das 'final' suggeriert eine immutabilität welche es nicht gibt.
Er nimmt völlig korrekt an, dass der Wert final ist und der Compiler dies sicherstellt, nichts ist da suggeriert.

Dee einzige, der falsches annimmt, ist der, der das final Feld über Reflection ändert und dabei annimmt, dass danach noch alles wie gewünscht funktionieren muss.
 
K

kneitzel

Wenn Du das nicht verstehst, bin ich nicht derjenige der kein Java kann... traurig.
Erläutere einfach Deine Aussage!

Ansonsten darf auch gerne jeder Andere Vermutungen anstellen, was Du meinst.

Ich würde halt Kritik gerne verstehen, auch wenn es hier mal wieder scheint, dass Du nur wieder in blinder Wut gegen mich agierst (wie schon öfters). Das ist aber Dein Problem und hier schlicht Off Topic.

Kritik an dem Code kann durchaus angebracht sein. Das mit dem direkten Zugriff auf die Felder habe ich ja erwähnt. Das mit dem final sehe ich nicht.

Falls Du meinen solltest, dass ich Versucht hätte die 3 Klassen versucht in einer abzubilden, dann liegt ein schlichter Kategorienfehler vor: Mir ging es nicht (wie bei Apache Commons) um die Bereitstellung möglichst universell einsetzbarer Klassen sondern lediglich um eine Lösung für die Thematik vom TE: Rückgabe von 2 Werten aus einer Methode.
(Und wenn man so eine Thematik / Anforderung implementiert, dann wird dies minimal gemacht. Oder entwickelst Du immer Dinge, die Du gar nicht brauchst?)
 
Ja nun gut, Du hattest zwei generische Parameter deklariert, diese aber nicht weiter auf nur immutable Typen eingeschränkt. Ich bin mir aber nicht sicher, ob das generell möglich wäre. Da also auch mutable Typen erlaubt sind, kann trotz 'final' deren Zustand geändert werden. Das 'final' drück lediglich aus, dass sich die Referenz nicht ändern darf. Das zu vermeiden ist nicht ganz trivial, man könnte Getter hinzufügen welche immer eine nicht flache Kopie des Typs zurückgeben wodurch das Tupel bei mutablen Typen konsistent bliebe. Alles zusammengefasst, TL;DR, finde ich aber, dass bei der Fragestellung des TE ein so hohes Design nicht angelegt werden sollte. Wenn ich vom Handy aus tippe, dann ich auch manches Q&D und sollte nur einen ersten Anlauf bieten. Und naja... Persönlich wollte ich generell gar nicht werden... Ich kenne die Ausdrücke und Schlüsselwörter 'final'.
 
Du hattest zwei generische Parameter deklariert, diese aber nicht weiter auf nur immutable Typen eingeschränkt. Ich bin mir aber nicht sicher, ob das generell möglich wäre.
Nein, ist es nicht.


Das 'final' drück lediglich aus, dass sich die Referenz nicht ändern darf.
Richtig, hat @kneitzel ja auch schon geschrieben. Und dadurch bringt final natürlich etwas (entgegen deine Aussage) und suggeriert nichts (entgegen deiner Aussage), sondern macht genau das, was es soll und was jeder Java-Entwickler erwartet.


Alles zusammengefasst, TL;DR, finde ich aber, dass bei der Fragestellung des TE ein so hohes Design nicht angelegt werden sollte.
Immutability wie du sie da vorschlägst ist wirklich völlig overengineered und so gut wie nie nötig - die Lösung von @kneitzel dagegen ist eine völlig übliche Standardlösung für genetische Tupel (bis auf weggelassenen Boilerplatecode), besser wäre für diesen Fall aber wirklich wie von @kneitzel gesagt eine extra Klasse.


Persönlich wollte ich generell gar nicht werden...
Dann solltest du es generell von vornherein lassen.
 
Passende Stellenanzeigen aus deiner Region:

Oben