ubuntuusers.de

[Java] Call by Value: auch Integer-Werte durch methode aendern

Status: Ungelöst | Ubuntu-Version: Nicht spezifiziert
Antworten |

dersven

Anmeldungsdatum:
16. August 2005

Beiträge: 792

Wohnort: Kreuzlingen, Schweiz

Hallo.

Auf http://www.java-forum.org/allgemeines/4904-call-value-call-reference.html habe ich eine ganz schoene erklaerung gefunden zu call-by-value und call-by-reference.

Allerdings weiss ich jetzt immer noch nicht genau, bei welchem DatenTypen ich den Wert mit einer methode innerhalb des Aufrufenden Datentyps aendern kann. Also, bei ArrayList geht es problemlos, aber was mache ich, wenn ich einen Integer-Wert aendern will? Ich hatte bis gerade eben die hoffnung, dass ich dann nicht einfach int, sondern die Wrapper-Klasse "Integer" nehme, aber das Klappt nicht:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.ArrayList;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated constructor stub
		
		ArrayList<Integer> liste = new ArrayList<Integer>();
		Integer zahl = new Integer(0);
		
		int doit = 10;
		Objekt objekt = new Objekt();
		
		for(int i=0; i<doit; i++) {
			objekt.addit(liste, zahl);
		}
		
		System.out.println("nerv1: " + liste.size());
		System.out.println("nerv2: " + zahl.intValue());
		
	}

}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import java.util.ArrayList;

public class Objekt {

	public Objekt() {
		
	}
	
	
	public void addit(ArrayList<Integer> liste, Integer zahl) {
		liste.add(1);
		zahl = 99;
	}

}

oder kann ich das jetzt nur fuer listen machen?, also Datentypen, die mehr als einen Wert enthalten? Mit einem Array der Länge 1 (int[0]) klappt es.

Oder gibt es irgendeine andere (elegante) Moeglichkeit, ansttt Listen mit nur einem Element zu übergeben?

Gruesse

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17622

Wohnort: Berlin

Methoden sollten wenn möglich den Wert zurückgeben.

public int addNeun (int zahl) 
{
	return 9 + zahl;
}

YEPHENAS

Anmeldungsdatum:
8. Juni 2009

Beiträge: 352

dersven schrieb:

Hallo.

Auf http://www.java-forum.org/allgemeines/4904-call-value-call-reference.html habe ich eine ganz schoene erklaerung gefunden zu call-by-value und call-by-reference.

Allerdings weiss ich jetzt immer noch nicht genau, bei welchem DatenTypen ich den Wert mit einer methode innerhalb des Aufrufenden Datentyps aendern kann. Also, bei ArrayList geht es problemlos, aber was mache ich, wenn ich einen Integer-Wert aendern will? Ich hatte bis gerade eben die hoffnung, dass ich dann nicht einfach int, sondern die Wrapper-Klasse "Integer" nehme, aber das Klappt nicht

Integer ist zwar ein Referenztyp, aber trotzdem immutable. Das nennt man so, wenn eine Klasse keine Methoden anbietet um ihren internen Zustand zu verändern. Wie der Vorposter schrieb sollten Funktionen ihre Ergebnisse über einen Rückgabewert zurückliefern und ansonsten möglichst Nebeneffektfrei bleiben (in funktionalen Programmiersprachen nimmt man das mit der Nebeneffektfreiheit sogar besonders genau, was dann auch bessere Parallelisierbarkeit mit sich bringt). Wenn du mehrere Objekte/Werte zurückliefern willst schreibst du dir einfach eine Wrapperklasse.

Java bietet eigentlich gar kein call-by-reference. Wertetypen werden by-value übergeben und Referenztypen werden reference-by-value übergeben. Klingt verwirrend, ist aber so. Du kannst zwar den internen Zustand eines übergebenen Objektes ändern, wenn es nicht immutable ist, aber nicht das übergebene Objekt selbst durch ein anderes austauschen.

Lunar

Anmeldungsdatum:
17. März 2006

Beiträge: 5792

@YEPEHNAS: Man nennt das call by object (aka call by sharing), „reference by value“ habe ich noch nie gehört.

YEPHENAS

Anmeldungsdatum:
8. Juni 2009

Beiträge: 352

Lunar schrieb:

@YEPEHNAS: Man nennt das call by object (aka call by sharing), „reference by value“ habe ich noch nie gehört.

Ok, was dazugelernt. Bei mir war es genau andersrum. ☺

dersven

(Themenstarter)

Anmeldungsdatum:
16. August 2005

Beiträge: 792

Wohnort: Kreuzlingen, Schweiz

user unknown schrieb:

Methoden sollten wenn möglich den Wert zurückgeben.

public int addNeun (int zahl) 
{
	return 9 + zahl;
}

Wenn möglich,...

Ich nutze die moeglichkeit recht haufig ein Objekt an eine Methode zu übergeben, und diese dann geaendert zurück zu bekommen.

Ich programmiere eine Art spiel. Ich habe ein Spielfeld, und auf jedem der Felder passiert nacheinander zu einem bestimmten Zeitpunkt etwas. Also gehe ich nacheinder alle Felder des Spielfeldes durch (uebergebe der Methode des Feldes das Spielfeld), schaue wie dieses feld die anderen Felder beeinflusst, und schreibe diese aenderungen in die beeinflussten felder.

Wie könnte ich das anders machen?

YEPHENAS

Anmeldungsdatum:
8. Juni 2009

Beiträge: 352

dersven schrieb:

Ich nutze die moeglichkeit recht haufig ein Objekt an eine Methode zu übergeben, und diese dann geaendert zurück zu bekommen.

Ich programmiere eine Art spiel. Ich habe ein Spielfeld, und auf jedem der Felder passiert nacheinander zu einem bestimmten Zeitpunkt etwas. Also gehe ich nacheinder alle Felder des Spielfeldes durch (uebergebe der Methode des Feldes das Spielfeld), schaue wie dieses feld die anderen Felder beeinflusst, und schreibe diese aenderungen in die beeinflussten felder.

Wie könnte ich das anders machen?

Für sowas ist das schon ok. Aber für Variablen von Typen wie int oder Integer, die eigentlich Werte repäsentieren sollen (deswegen ist Integer auch immutable) ist das nicht üblich (sie als Methodenparameter ändern zu wollen). Du kannst call-by-reference natürlich simulieren, indem du z.B. eine Klasse ObjectWrapper<T> erstellst, die ein einziges Objekt aufnimmt, und dann übergibst du eine solche ObjectWrapper-Instanz an die Methode. Das wäre äquivalent zu deinem Array-mit-einem-Element-Ansatz, ist aber völliger Overkill.

Marc_BlackJack_Rintsch Team-Icon

Ehemalige
Avatar von Marc_BlackJack_Rintsch

Anmeldungsdatum:
16. Juni 2006

Beiträge: 4694

Wohnort: Berlin

@dersven: Ich verstehe nicht so ganz was Du da jetzt anders machen willst, denn ich sehe in der Beschreibung das Problem nicht, dass Du im ersten Beitrag beschreibst!?

Denn Du brauchst ja wohl in der Methode Zugriff auf eine Art Spielkarten-Objekt, in dem alle Felder auf der Karte zusammengefasst sind, also entweder über die Instanz oder als Argument, je nachdem wo die Methode steht. Und das sollte natürlich nicht "immutable" sein, denn ein Spiel bei dem man den Inhalt der Spielfelder nicht ändern kann, dürfte ziemlich langweilig sein. Ungetestetes Beispiel für eine Aktualisierungsfunktion, die abfragt, ob ein Feld einen Wert von mindestens der Anzahl der Nachbarfelder hat, und wenn ja den Wert entsprechend verringert und dafür alle Nachbarfelder um eins erhöht:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
    public static void update(Map map, int x, int y) {
        List<Coordinate> neighbours = map.getNeighboursOf(x, y);
        int neighbourCount = neighbours.size();
        if (map.getValueAt(x, y) >= neighbourCount) {
            map.decreaseValueAt(x, y, neighbourCount);
            for (Coordinate coordinate : neighbours) {
                map.increaseValueAt(coordinate.x, coordinate.y, 1);
            }
        }
    }

Wenn man keine "externen", austauschbaren Regeln braucht, kann man update() auch als Methode auf Map implementieren.

Antworten |