Verwendet Java Zeiger oder Referenzen? (Was für den Experten)
-
Mir ist bekannt das Objekte in Java über so genannte "Reference Values" angesprochen werden und das in vielen Büchern steht, das Java keine Zeiger verwenden würde. Stattdessen wird immer wieder gerne von Referenzen gesprochen. Ich halte die Auffassung jedoch für grundlegend falsch.
Ich bin der Meinung das Java eingeschränkte Zeiger verwendet, da einem "Reference Value" zur Laufzeit unterschiedliche Objekte zugewiesen werden können, was bei einer Referenz (Alias) nicht möglich ist und mit der Deklaration initialisiert werden muss.
So ändert beispielsweise in C/C++ eine mit Referenzen definierte swap() Funktion auch die Werte außerhalb der Funktion selbst, während in Java nur die Objekte untereinander getauscht werden, was außerhalb der Funktion aber nicht sichtbar ist.
Swap mit Referenzen in C/C++
void swap(type &a, type &b) { type t = a; a = b; b = t; } void main() { type x = 3; type y = 4; swap(x,y); // x ist nun 4 und y = 3 }
Swap mit Java
public void swap(Object a, Object b) { Object t = a; a = b; b = t; } public static void main(String[] args) { Object x = new Double(3); Object y = new Double(4); swap(x,y); // x ist immer noch 3 und y immer noch 4 // Die swap-Funktion ist also sinnlos }
-
Definier halt erstmal, was ein Zeiger, was eine Referenz ist. Die Java-Designer verwenden anscheinend eine andere Definition als Du, damit hat sich die Diskussion eigentlich erledigt.
-
Java Referenzen == Zeiger
Das Wort "Referenzen" ist nur Marketing Blabla. Klingt vermutlich besser/sicherer als Zeiger.
-
this->that schrieb:
Java Referenzen == Zeiger
Das Wort "Referenzen" ist nur Marketing Blabla. Klingt vermutlich besser/sicherer als Zeiger.
So denke ich das ja auch, schließlich schreibt ja selbst Sun in der Sprachdefinition: "The reference values (often just references) are pointers to these objects, and a special null reference, which refers to no object."[1]
Liegt wohl doch einfach daran, das Sun hier den Begriff der Referenz (Alias) einfach umdefiniert hat und für "kastrierte" Zeiger verwendet.
-
niabot schrieb:
Liegt wohl doch einfach daran, das Sun hier den Begriff der Referenz (Alias) einfach umdefiniert hat und für "kastrierte" Zeiger verwendet.
Dieser Begriff, Referenz = Alias, ist aber eine C++-Spezialität. Ich würde da nicht von umdefinieren sprechen, Zeiger hat man auch vor Java schon Referenzen genannt.
-
Bashar schrieb:
niabot schrieb:
Liegt wohl doch einfach daran, das Sun hier den Begriff der Referenz (Alias) einfach umdefiniert hat und für "kastrierte" Zeiger verwendet.
Dieser Begriff, Referenz = Alias, ist aber eine C++-Spezialität.
Nein, Fortran folgt dieser Sprachregelung ebenfalls. Fortran (die älteste noch regelmäßig genutzte Programmiersprache) übergibt alle Parameter einer Funktion via Referenz, und man kann diese Referenz nicht verändern. Zeiger (die gibt es mittlerweile) in Fortran sind bedeutungsgleich mit Referenzen in Java. Pascal folgt ebenfalls dieser Sprachregelung.
Die Zeiger in Java sind rein aus Marketinggründen Referenzen genannt worden, damit wohl der Aspekt der fehlenden Zeigerarithmetik stärker betont wird. Aber in vielen anderen Programmiersprachen gibt es ebenfalls keine Zeigerarithmetik und man nennt das Sprachkonstrukt trotzdem Zeiger.
-
~john schrieb:
Nein, Fortran folgt dieser Sprachregelung ebenfalls.
Ich rede von Referenztypen, nicht von call-by-reference. Erstere gibt es in Fortran meines Wissens nicht. In Pascal, was du auch genannt hattest, auf keinen Fall.
-
~john schrieb:
Aber in vielen anderen Programmiersprachen gibt es ebenfalls keine Zeigerarithmetik und man nennt das Sprachkonstrukt trotzdem Zeiger.
Zum Beispiel?
-
NullPointerException vs. NullReferenceException
-
Bashar schrieb:
~john schrieb:
Nein, Fortran folgt dieser Sprachregelung ebenfalls.
Ich rede von Referenztypen, nicht von call-by-reference. Erstere gibt es in Fortran meines Wissens nicht. In Pascal, was du auch genannt hattest, auf keinen Fall.
Ich rede ganz bewußt vom Konzept der Referenz, und das ist wie bereits beschrieben so alt wie Programmiersprachen nur sein könnten, und ja man kann in Fortran derselben Variablen verschiedene Namen verpassen, siehe EQUIVALENCE und COMMON. Auch wenn ich persönlich das Zeug als Hexengebräu bezeichne, und EQUIVALENCE das Analogon zu C unions ist. COMMON Blöcke (seit FORTRAN II dabei) erfüllen den Job einer Referenz, wenn man sie so eingesetzt hat. Beide Konstrukte sollte man in neuem Code nicht mehr verwenden.
-
~john schrieb:
Ich rede ganz bewußt vom Konzept der Referenz
Es geht aber hier nicht um das Konzept sondern um das Wort.
-
Leicht OT: Abgesehen davon, dass man es wahrscheinlich nicht braucht, könnte man eine Swap-Mehtode in Java mittels eines Wrapper-Objects realisieren (Java.lang.Integer kann man hier leider nicht nehmen, da diese Immutable ist)
class Test { public static void main(String[] args) { MutableInt a = new MutableInt(1); MutableInt b = new MutableInt(2); swap(a, b); a.swap(b); // oder als Obekt-Methode verwenden System.out.println("a=" + a + " b=" + b); } public static void swap(MutableInt a, MutableInt b) { MutableInt tmp = new MutableInt(a.value); a.value = b.value; b.value = tmp.value; } public static class MutableInt { public int value; public MutableInt(int value) {this.value = value;} public String toString() {return Integer.toString(value);} public void swap(MutableInt b) {int tmp = value; value = b.value; b.value = tmp;} } }
Eine andere Möglichkeit wäre z.B. ein Array anstatt dem Wrapper-Object zu nehmen und Inhalte zu vertauschen.
-
Bashar schrieb:
~john schrieb:
Ich rede ganz bewußt vom Konzept der Referenz
Es geht aber hier nicht um das Konzept sondern um das Wort.
Das ist das Problem mit ~john, er redet immer am Thema vorbei.
-
als java rauskam wurde oft beworben das es "no memory leaks" und "no wild pointer" gibt, weil es keine pointer gibt.
ich denke die differenzierung ist 99% marketing, aber auch ein wenig wahr, denn auf "irgendwas" kann man nicht zeigen, es gibt immer ein objekt auf das verwiesen wird (das ist ja auch bei c++ references der fall, sofern man nicht von ptr references erstellt). null in java ist auch ein objekt.
-
raps schrieb:
null in java ist auch ein objekt.
Sicher nicht. Null ist ein Wert der Referenz.
-
raps schrieb:
ich denke die differenzierung ist 99% marketing, aber auch ein wenig wahr, denn auf "irgendwas" kann man nicht zeigen, es gibt immer ein objekt auf das verwiesen wird (das ist ja auch bei c++ references der fall, sofern man nicht von ptr references erstellt). null in java ist auch ein objekt.
In C++ kann ich mittels
new
ein Objekt anlegen und mir eine Referenz darauf anlegen. Gebe ich jetzt das Objekt mittelsdelete
frei, so "zeigt" die zugehoerige Referenz auf nichts.null
ist in Java auch keine Objekt, da es sonst von Object erben wuerde und ich z.B. die MethodetoString
aufrufen koennte.
-
Ich denke, raps hat insofern Recht, als es in Java keine Dangling Pointers gibt. Man kann zwar logisch unsinnige Referenzen haben und z.B. Objekte zu lange am Leben erhalten, aber ein Nicht-Null-Zeiger kann immer dereferenziert werden. Ob das nun ein wesentlicher Vorteil ist oder das "Kein Absturz -> funktioniert"-Prinzip fördert, ist eine andere Frage...
@robot: Das Problem ist, dass ein
swap()
in Java nicht gut in bestehende Dinge integrierbar ist. Man muss jeweils eine separate Wrapper-Klasse verwenden. Und da ist ein Inline-Dreieckstausch halt oft einfacher.