Java: Wie byte [] durch Verweis übergeben?
-
22-07-2019 - |
Frage
Sie können unter dem Stichwort „ref“ es in .NET tun. Gibt es eine Möglichkeit, um in Java zu tun?
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
Minor Mods reqd: Verwenden Sie hashCode () und + verketten Zeichenfolgen in Counter.java ... .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
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
}