Java:如何通过引用传递字节 []?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/333151/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java: How to pass byte[] by reference?
提问by Mahendra
You can do it in .NET by using the keyword "ref". Is there any way to do so in Java?
您可以在 .NET 中使用关键字“ref”来完成。有没有办法在Java中这样做?
采纳答案by Jon Skeet
What are you doing in your method? If you're merely populating an existing array, then you don't need pass-by-reference semantics - either in .NET or in Java. In both cases, the reference will be passed by value - so changes to the objectwill be visible by the caller. That's like telling someone the address of your house and asking them to deliver something to it - no problem.
你用你的方法做什么?如果您只是填充现有数组,那么您不需要传递引用语义 - 无论是在 .NET 中还是在 Java 中。在这两种情况下,引用都将按值传递 - 因此调用者可以看到对对象的更改。这就像告诉某人您房子的地址并要求他们送东西一样 - 没问题。
If you reallywant pass-by-reference semantics, i.e. the caller will see any changes made to the parameter itself, e.g. setting it to null or a reference to a different byte array, then either method needs to return the new value, or you need to pass a reference to some sort of "holder" which contains a reference to the byte array, and which can have the (possibly changed) reference grabbed from it later.
如果您真的想要传递引用语义,即调用者将看到对参数本身所做的任何更改,例如将其设置为 null 或对不同字节数组的引用,那么任一方法都需要返回新值,或者您需要传递对某种“持有者”的引用,其中包含对字节数组的引用,并且稍后可以从中获取(可能已更改的)引用。
In other words, if your method looks likes this:
换句话说,如果您的方法如下所示:
public void doSomething(byte[] data)
{
for (int i=0; i < data.length; i++)
{
data[i] = (byte) i;
}
}
then you're fine. If your method looks like this:
那你就没事了。如果您的方法如下所示:
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;
}
}
then you need to change it to either:
那么您需要将其更改为:
public byte[] createArray(int length)
{
byte[] data = new byte[length];
for (int i=0; i < data.length; i++)
{
data[i] = (byte) i;
}
return data;
}
or:
或者:
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;
}
}
For more details, read Parameter passing in C#and Parameter passing in Java. (The former is better written than the latter, I'm afraid. One day I'll get round to doing an update.)
欲了解更多详情,请阅读参数传递的C#和参数传递在Java中。(恐怕前者写得比后者好。总有一天我会抽空更新一下。)
回答by Gishu
Java uses pass by value for method arguments.
Java 对方法参数使用按值传递。
- Primitives(int, boolean, etc.) are special cases in Java.. not objects per se. In this case, a copy of the primitive (argument) is passed into the function. This gels well with the pass by value theory.
- For Objects, what happens is that the ref to the object is passed by value (a copy of the reference is made rather than the object)... but both references point to the same object. So if you modify an object parameter in a method, the actual object will be modified.
- 基元(int、boolean 等)是 Java 中的特例……不是对象本身。在这种情况下,原语(参数)的副本被传递到函数中。这与价值传递理论很好地结合在一起。
- 对于对象,发生的情况是对象的引用是按值传递的(创建引用的副本而不是对象)……但是两个引用都指向同一个对象。所以如果你在一个方法中修改了一个对象参数,实际的对象将被修改。
This article should help you out.. http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
这篇文章应该可以帮助你.. http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
As for the OP's question, just pass in the reference to the byte[] array to the method. The net result would be similar to pass by reference. If you modify the byte array, the caller will be able to see the changes post method execution.
至于 OP 的问题,只需将对 byte[] 数组的引用传递给该方法。最终结果将类似于通过引用传递。如果修改字节数组,调用者将能够在方法执行后看到更改。
Update to quell the resistance :)=> indicates output
更新以平息阻力:)=> 表示输出
.NET Land
.NET 土地
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: Use hashCode() and + to concat strings in Counter.java...
次要模组要求:使用 hashCode() 和 + 来连接 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
}
回答by coobird
Actually, in Java, the references are passed-by-value.
实际上,在 Java 中,引用是按值传递的。
In this case, the reference is a byte[]
object. Any changes that affect the object itself will be seen from the caller method.
在这种情况下,引用是一个byte[]
对象。任何影响对象本身的更改都可以从调用方方法中看到。
However, if you try to replace the reference, for example using new byte[length]
, you are only replacing the reference that you obtained by pass-by-value, so you are not changing the reference in the caller method.
但是,如果您尝试替换引用,例如使用 new byte[length]
,您只会替换通过值传递获得的引用,因此您不会更改调用方方法中的引用。
Here's an interesting read about this issue: Java is Pass-by-Value Dammit!
这里有一个关于这个问题的有趣读物:Java is Pass-by-Value Dammit!
Here's an concrete example:
这是一个具体的例子:
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);
}
}
This program will create a byte
array of length 8
in the main
method, which will call the modifyArray
method, where the a new byte
array of length 16
is created.
该程序将在方法中创建一个byte
长度数组,8
该main
方法将调用该modifyArray
方法,在该方法中创建一个新byte
的长度数组16
。
It may appear that by creating a new byte
array in the modifyArray
method, that the length of the byte
array upon returning to the main
method will be 16
, however, running this program reveals something different:
看起来,通过byte
在modifyArray
方法中创建一个新数组,byte
返回到main
方法时数组的长度将是16
,但是,运行此程序会揭示一些不同的东西:
Before Method: Length: 8
Method Entry: Length: 8
Method Exit: Length: 16
After Method: Length: 8
The length of the byte
array upon returning from the modifyArray
method reverts to 8
instead of 16
.
byte
从modifyArray
方法返回时,数组的长度恢复为8
而不是16
。
Why is that?
这是为什么?
That's because the main
method called the modifyArray
method and sent a copied reference to the new byte[8]
by using pass-by-value. Then, the modifyArray
method threw away the copied reference by creating a new byte[16]
. By the time we leave modifyArray
, the reference to the new byte[16]
is out of scope (and eventually will be garbage collected.) However, the main
method still has reference to the new byte[8]
as it only sent the copied referenceand not an actual reference to the reference.
那是因为该main
方法调用了该modifyArray
方法并使用pass-by-value发送了对 的复制引用new byte[8]
。然后,该方法通过创建一个. 到我们离开时,对 的引用已超出范围(最终将被垃圾收集。)但是,该方法仍然有对 的引用,因为它只发送了复制的引用,而不是对引用的实际引用。modifyArray
new byte[16]
modifyArray
new byte[16]
main
new byte[8]
That should demonstrate that Java will pass reference using pass-by-value.
这应该表明 Java 将使用按值传递来传递引用。