Was ist der Unterschied zwischen in Java durch Bezugnahme geben und einen Zeiger in C vorbei?

StackOverflow https://stackoverflow.com/questions/600651

Frage

Ich habe für ein paar Monate Java studiert und bin ab jetzt C lernen

Ich bin ein wenig verwirrt, ich habe den Eindruck, dass ein Objekt als Verweis vorbei und einen Zeiger auf das Objekt verläuft die gleiche Sache war: dachte ich, der Unterschied war, dass alle Vergehen von Objekten in Java mit Zeigern automatisch erfolgt, wo, wie in C einen eigentlich hat zu streuen kleine Sternchen und hier und da Et-Zeichen. Vor kurzem im Gespräch, wurde mir versichert, dass es einen Unterschied war!

Was ist der Unterschied zwischen durch Bezugnahme vorbei und einen Zeiger vorbei?

War es hilfreich?

Lösung

Weder Java noch C hat pass-by-reference. Sie sind beide streng Pass-by-Wert.

Pass-by-reference Semantik bedeutet, dass, wenn Sie den Wert des Parameters in dem Verfahren ändern, der Anrufer, dass die Änderung des Argument sehen.

Nun können Sie denken: „Aber das ist der Fall in Java Wenn ich ein Objekt während des Verfahrens zu ändern, sieht der Anrufer, dass der Wandel!“. Das Objekt ist nicht der Parameter Der Parameter ist nur die Variable -. Und wenn Sie den Wert dieser Variablen ändern, wird der Anrufer nicht sehen. Zum Beispiel:

public void foo(Object x)
{
    x = null;
}

public void caller()
{
    Object y = new Object();
    foo(y);
    // y is still not null!
}

Wenn die Parameter sind wirklich als Referenz übergibt, würde y danach null sein. Stattdessen ist der Wert von y nur eine Referenz, und das Referenz wird durch Wert übergeben. Es ist verwirrend, weil das Wort „Referenz“ in beiden Begriffen ist, aber sie sind verschiedene Dinge.

Sie können unter meinem Artikel über C # Parameter übergeben aussehen wollen, um zu sehen was möglich wäre, wenn Java haben haben pass-by-reference Semantik, wie C # tut, wenn (und nur wenn) Sie ref Schlüsselwort verwenden.

Sie können auch auf die Kommentare aussehen wollen href="https://stackoverflow.com/questions/423823/whats-your-favorite-programmer-ignorance-pet-peeve/423833#423833"> Zusammenhang mit dem Thema.

Andere Tipps

  

dachte ich, der Unterschied war, dass in Java alle Weitergabe von Objekten mit Zeigern automatisch durchgeführt wird, wo, wie in C eine kleines Sternchen und Et-Zeichen muss hier und da tatsächlich bestreuen.

Conceptional, das ist ganz richtig. Wenn wir pedantisch sind (und das ist eine gute Sache), können wir sogar sagen, Objekte werden nicht in Java übergeben. Was passiert ist immer nur der „Zeiger“, die in Java wird die Referenz genannt. Alle indirection erfolgt automatisch. Also, wenn Sie das tun „objref-> foo“ statt „objref.foo“ in C und können nicht den Punkt verwenden, da Sie mit einem Zeiger arbeiten, in Java können Sie den Punkt verwenden, weil es nichts weiß anderes zu Zugang Mitglieder sowieso. In C, können Sie den Zeiger passieren kann (und hier, es ist eigentlich genannt Zeiger) und Sie das Objekt passieren kann selbst in diesem Fall eine Kopie übergeben wird. In C, greifen Sie auf das Objekt, das ein Zeiger auf auf Umwegen bezieht sich mit dem Stern oder „->“. In Java sind die einzige Möglichkeit, Objekte ohnehin mit dem Punkt (objref.member) abgerufen.

Wenn wir wieder pedantisch (jetzt wieder wichtiger), weder in Java noch in C gibt es „als Verweis übergeben“. Was wir in Java übergeben ist der Verweis / Zeiger auf das Objekt und in C wir entweder eine Kopie des Objekts (offensichtlichste Fall) passieren oder passieren wir wieder nur eine Kopie eines Zeigers auf das Objekt. Also in beiden Fällen - Java und C - was passieren wir die Adressen der Objekte. Nicht redete über primitive Java-Typen, die in Java und C kopiert werden - auch wenn Sie ihre Adresse in C auch passieren kann, gibt es keinen Unterschied zwischen einem Aggregat-Typ (dh eine Struktur) und einem „Urtyp“ in C in < em>, die Hinweis.

Die Unterschiede sind subtil. An einer Montageebene, in beiden Fällen ist die Adresse des Objekts an die Funktion übergeben. im Zeiger Fall jedoch der Parameter ist ein unabhängiger Zeiger, die verwendet werden können, um das Zielobjekt (* PCH = ‚x‘) verwendet werden kann oder zu modifizieren, um ein anderes Objekt zuzugreifen (PCH = „newstr“). Im Referenzfall wird der Parameter auf das Zielobjekt automatisch indirected.

Wenn Sie studieren C (statt C ++), dann gibt es keine Hinweise.

Der Begriff „als Verweis übergibt“ in C bedeutet einfach, dass Sie einen Zeiger als Adresse sind vorbei, in dem der Wert gespeichert werden, so dass die Funktion ihren Wert ändern kann. Andernfalls werden Sie von Wert vorbei, was bedeutet, dass eine Kopie der Variablen auf dem Stapel erzeugt und Änderungen haben keine Auswirkungen.

In vielerlei Hinsicht ist dies ähnlich dem, was Sie sehen in Java, mit der Ausnahme, dass in Java Sie müssen nicht explizit Dinge in einen Zeiger drehen oder dereferenzieren sie. Mit anderen Worten, wenn Sie einen Zeiger übergeben, wird die Adresse auf dem Stack kopiert, so dass, wenn Ihre Funktion den Zeiger (anstatt die Daten verweist er auf) ändert, werden die Änderungen verschwinden, wenn Sie mit der Funktion fertig sind. Ebenso, wenn Sie einen Objektverweis in Java übergeben, können Sie den Inhalt des Objekts ändern (zum Beispiel durch den Aufruf von Funktionen), aber die Änderung der varialbe bei anothr Objekt zeigt keine Wirkung, wenn Sie verlassen.

Wenn Sie C wurden mit ++ (die wie C aussieht), dann können Sie durch Verweis übergeben, in dem Fall, dass Sie nicht brauchen, um mit Zeigern zu umgehen, und Änderungen an die Variablen in der Funktion tatsächlich den Außenwert direkt ändern ( außer dass Sie es nicht auf etwas anderes hinweisen machen kann).

Es gibt einen kürzlich erschienenen Artikel von Eric Lippert darüber. Er ist ein Programmierer auf dem C # -Compiler, aber alles, was er sagt, es hat genug Allgemeinheit auf andere GC-Sprachen wie Java erweitert werden:

http: // blogs .msdn.com / ericlippert / Archiv / 2009/02/17 / Referenzen-sind-nicht-addresses.aspx

Zitat aus dem Artikel:

  

Pointers sind streng „mächtiger“ als Referenzen; alles können Sie mit Referenzen tun Sie mit Zeigern tun. [...]

     

Pointers werden typischerweise als Adressen implementiert. Eine Adresse ist eine Zahl, die in den „Byte-Array“ Offset wird, daß der gesamte virtuelle Adreßraum des Prozesses ist. [...]

     

Aus all diesen Gründen beschreiben wir keine Referenzen als Adressen in der Beschreibung. Die Spezifikation sagt nur, dass eine Variable von Referenz-Typ „speichert eine Referenz“ auf ein Objekt, und überlässt es völlig vage, wie das umgesetzt werden könnte. Ähnlich wird eine Zeigervariable speichert „die Adresse“ eines Objekts, das wiederum links ist ziemlich vage. Nirgends wir sagen, dass Referenzen die gleichen wie Adressen sind.

     

in C # ist also eine Referenz eine vage Sache, dass Sie ein Objekt verweisen können. Sie können nicht mit einem Verweis alles tun, außer dereferenzieren, und vergleichen Sie es mit einem anderen Bezug auf Gleichheit. Und in C # ein Zeiger wird als eine Adresse identifiziert.

     

Im Gegensatz zu einer Referenz, können Sie viel mehr mit einem Zeiger tun, die eine Adresse enthält. Adressen können mathematisch manipuliert werden; Sie können voneinander subtrahieren, können Sie ganze Zahlen zu ihnen, und so weiter hinzuzufügen. Ihre rechtlichen Operationen zeigen, dass sie „fancy Zahlen“, dass Index in die „Array“, das der virtuelle Adressraum des Prozesses ist.

Die Leser vertraut mit C / C ++ wahrscheinlich bemerkt haben, dass Objektreferenzen erscheinen ähnlich wie Zeiger sein. Dieser Verdacht ist im Wesentlichen richtig. Eine Objektreferenz ist ähnlich einem Speicherzeiger. Der Hauptunterschied-und der Schlüssel zu Java sicherheits ist, dass Sie können keine Hinweise, wie Sie können tatsächliche Zeiger manipulieren. So können Sie nicht dazu führen, Objektreferenz auf eine beliebige Speicherstelle zeigen oder es wie eine ganze Zahl zu manipulieren.

  • Java nicht unterstützt Operator & wie kann dann u Objektadresse in Java erhalten.
  • In Java-Referenz wird zum Beispiel durch das Objekt durchgeführt

MyClass object1 = new MyClass ();

MyClass object2 = object1;

d. Sie könnten, dass object1 denken und object2 beziehen und verschiedene Objekte zu trennen. Allerdings wäre dies falsch. Stattdessen nachdem dieses Fragment führt, und object1 object2 werden beide auf dasselbe Objekt beziehen. wenn Sie in einem anderen Effekt geändert werden.

* cann't Sie die Adresse des Objekts ändern, nachdem initialize d.h MyClass obj = new MyClass (); als Referenz in C ++, mit dem Objekt können Sie nur Instanz Objektwert ändern

Hinweis: Java bietet eine Besonderheit         object1 wurde auf null gesetzt, aber Object2 immer noch auf das ursprüngliche Objekt.

Ich bin mir nicht sicher java aber in C # oder VB.net Sie nach Wert oder refrence passieren kann

Beispiel durch refrence vorbei

    static void Main(string[] args)
    {
        int x = 1;
        Foo(ref x);
        Console.WriteLine(x.ToString());//this will print 2
    }

    private static void Foo(ref int x)
    {
        x++;
    }

Beachten Sie, dass x gleich 1 ist, aber wenn Sie die Methode Foo aufrufen und vorbei x von refrence wenn x um eins in Foo der ursprüngliche Wert erhöht auch erhöht wird,

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top