Frage

Sie können unter dem Stichwort „ref“ es in .NET tun. Gibt es eine Möglichkeit, um in Java zu tun?

War es hilfreich?

Lösung

Was Sie in Ihrer Methode zu tun? Wenn Sie nur ein vorhandenes Array bevölkern, dann brauchen Sie nicht pass-by-reference Semantik - entweder in .NET oder Java. In beiden Fällen wird die Referenz von Wert übergeben werden - so Änderungen an das Objekt wird durch den Anrufer sichtbar. Das ist wie jemand die Adresse Ihres Hauses zu erzählen und bittet sie, etwas, um es zu liefern -. Kein Problem

Wenn Sie wirklich wollen pass-by-reference Semantik, das heißt der Anrufer werden alle Änderungen sehen an den Parameter vorgenommen selbst, zum Beispiel Setzt sie auf einen anderen Byte-Array auf null oder ein Verweis, dann muss entweder Methode den neuen Wert zurückzukehren, oder Sie müssen einen Verweis auf eine Art „Halter“ zu übergeben, die einen Verweis auf den Byte-Array enthält, und welche haben der (möglicherweise geändert) Bezug von ihm griff später.

Mit anderen Worten, wenn Ihre Methode sieht gefällt das:

public void doSomething(byte[] data)
{
    for (int i=0; i < data.length; i++)
    {
        data[i] = (byte) i;
    }
}

dann bist du gut. Wenn Ihre Methode sieht wie folgt aus:

public void createArray(byte[] data, int length)
{
    // Eek! Change to parameter won't get seen by caller
    data = new byte[length]; 
    for (int i=0; i < data.length; i++)
    {
        data[i] = (byte) i;
    }
}

, dann müssen Sie es ändern entweder:

public byte[] createArray(int length)
{
    byte[] data = new byte[length]; 
    for (int i=0; i < data.length; i++)
    {
        data[i] = (byte) i;
    }
    return data;
}

oder:

public class Holder<T>
{
    public T value; // Use a property in real code!
}

public void createArray(Holder<byte[]> holder, int length)
{
    holder.value = new byte[length]; 
    for (int i=0; i < length; i++)
    {
        holder.value[i] = (byte) i;
    }
}

Für weitere Details lesen Sie Parameterübergabe in C # und Parameter in Java vorbei. (Ersteres ist besser geschrieben als letzterer ist, fürchte ich. Eines Tages werde ich umgehen werde, ein Update zu tun.)

Andere Tipps

Eigentlich in Java, die Referenzen sind vergangen-by-Wert .

In diesem Fall ist die Referenz ein byte[] Objekt. Alle Änderungen, die das Objekt betreffen selbst werden von dem Anrufer Methode gesehen werden.

Wenn Sie jedoch versuchen, die Referenz, beispielsweise mit new byte[length] zu ersetzen, die Sie ersetzen nur die Referenz, die Sie durch Pass-by-Wert erhalten, so dass Sie die Referenz in der Anrufer Methode nicht ändern.

Hier ist eine interessante Lektüre zu diesem Thema: Java ist Pass-by-Wert Dammit


Hier ist ein konkretes Beispiel:

public class PassByValue
{
    public static void modifyArray(byte[] array)
    {
        System.out.println("Method Entry:  Length: " + array.length);
        array = new byte[16];
        System.out.println("Method Exit:   Length: " + array.length);
    }

    public static void main(String[] args)
    {
        byte[] array = new byte[8];
        System.out.println("Before Method: Length: " + array.length);
        modifyArray(array);
        System.out.println("After Method:  Length: " + array.length);
    }
}

Dieses Programm wird eine byte Array der Länge 8 im main Verfahren erstellen, die die modifyArray Methode nennen, wo das eine neue byte Array der Länge 16 erstellt wird.

Es kann vorkommen, dass durch eine neue byte Array in dem modifyArray Verfahren zu schaffen, dass die Länge des byte Array auf die main Verfahren nach der Rückkehr wird anders 16 ich jedoch, verrät etwas dieses Programm ausgeführt wird:

Before Method: Length: 8
Method Entry:  Length: 8
Method Exit:   Length: 16
After Method:  Length: 8

Die Länge des Arrays auf byte vom modifyArray Verfahren Rückkehr kehrt anstelle von 8 16.

Warum?

Das ist, weil die main Methode, um die modifyArray Verfahren und gesendet ein kopiertes Verweis auf die new byte[8] , indem Sie Pass-by-Wert bezeichnet. Dann wird die modifyArray Methode warf durch die Schaffung eines new byte[16] den kopierten Referenz entfernt . Als wir modifyArray, der Verweis auf die new byte[16] verlassen ist außerhalb des Gültigkeitsbereichs (und wird schließlich sein Müll gesammelt.) Allerdings hat die main Verfahren noch Bezug auf die new byte[8], da es nur schickte die kopierten Referenz und nicht eine tatsächliche Bezugnahme auf den Bezug genommen wird.

Das sollte zeigen, dass Java passiert Referenz verwendet Pass-by-Wert.

Java verwendet Pass von Wert für Methodenargumente .

  • Primitives (int, boolean, etc in Java.) sind Spezialfälle .. Objekte nicht per se. In diesem Fall wird eine Kopie des ursprünglichen (Argument) in die Funktion übergeben. Diese Gele gut mit dem Pass von Werttheorie.
  • Für Objekte, was passiert ist, dass der Schiedsrichter auf das Objekt als Wert übergeben wird (eine Kopie des Bezugs genommen wird, anstatt das Objekt) ... aber beide Referenzen auf das gleiche Objekt zeigen. Also, wenn Sie ein Objekt Parameter in einem Verfahren ändern, wird das eigentliche Objekt geändert werden.

Dieser Artikel soll Ihnen helfen .. http://www.javaworld.com/ Javaworld / javaqa / 2000-05 / 03-de-0526-pass.html

Was die Frage des OP, passiert nur im Bezug auf die byte [] Array auf das Verfahren. Das Nettoergebnis wäre ähnlich durch Verweis übergeben. Wenn Sie den Byte-Array ändern, wird der Anrufer in der Lage die Änderungen post-Methode Ausführung zu sehen.

) => gibt Ausgang

Aktualisieren, um den Widerstand zu bezwingen

.NET Land

class Counter
{
  private int m_count = 0;
  public override string  ToString()
  {
     return String.Format("Counter ID{0} : Value {1}", this.GetHashCode(), m_count);
  }
  public void Increment()
  {  m_count++;  }
}
class MakeAPass
{
   public void PassByValueAndModify(int i)
   {   i = 20;    }

   public void PassByRefAndModify(ref int i)
   {   i = 20;   }

   public void PassByValueAndModify(Counter c)
   {   c.Increment();   }

   public void PassByRefAndModify(ref Counter c)
   {   c.Increment();   }

   public void PassByRefAndReassign(ref Counter c)
   {
      c = new Counter();
      for (int i=0; i<5; ++i)
         c.Increment();
   }
}

static void Main(string[] args)
{
   MakeAPass obj = new MakeAPass();
   int intVal = 10;
   obj.PassByValueAndModify(intVal);
   Console.WriteLine(intVal);              // => 10
   obj.PassByRefAndModify(ref intVal);
   Console.WriteLine(intVal);              // => 20

   Counter obCounter = new Counter();
   obj.PassByValueAndModify(obCounter);
   Console.WriteLine(obCounter.ToString());  // => Counter ID58225482 : Value 1
   obj.PassByRefAndModify(ref obCounter);
   Console.WriteLine(obCounter.ToString());  // => Counter ID58225482 : Value 2
   obj.PassByRefAndReassign(ref obCounter);
   Console.WriteLine(obCounter.ToString());  // => Counter ID54267293 : Value 5
}

Java Land

Minor Mods reqd: Verwenden Sie hashCode () und + verketten Zeichenfolgen in Counter.java ...

class MakeAPass
{
   public void PassByValueAndModify(int i)
   {   i = 20;   }

   // can't be done.. Use Integer class which wraps primitive
   //public void PassByRefAndModify(ref int i)

   public void PassByValueAndModify(Counter c)
   {   c.Increment();   }

   // same as above. no ref keyword though
   //public void PassByRefAndModify(ref Counter c)

   // this can't be done as in .net
   //public void PassByRefAndReassign(ref Counter c)
   public void PassAndReassign(Counter c)
   {
      c = new Counter();
      for (int i=0; i<5; ++i)
         c.Increment();
   }
}
public static void main(String args[])
{
   MakeAPass obj = new MakeAPass();
   int intVal = 10;
   obj.PassByValueAndModify(intVal);
   System.out.println(intVal);                 // => 10 
   //obj.PassByRefAndModify(ref intVal);
   //System.out.println(intVal);               // can't get it to say 20

   Counter obCounter = new Counter();
   obj.PassByValueAndModify(obCounter);
   System.out.println(obCounter.ToString());    // => Counter ID3541984 : Value 1
   //obj.PassByRefAndModify(ref obCounter);
   //Console.WriteLine(obCounter.ToString());   // no ref. but can make it 2 by repeating prev call
   obj.PassAndReassign(obCounter);
   System.out.println(obCounter.ToString());    // => Counter ID3541984 : Value 1
                                                // can't get it to say 5  
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top