您可以使用关键字"ref"在.NET中执行此操作.有没有办法在Java中这样做?
你在用你的方法做什么?如果您只是填充现有数组,那么您不需要传递引用语义 - 无论是在.NET中还是在Java中.在这两种情况下,引用都将按值传递 - 因此调用者可以看到对象的更改.这就像告诉别人你的房子的地址,并要求他们提供一些东西 - 没问题.
如果你真的想要传递引用语义,即调用者将看到对参数本身所做的任何更改,例如将其设置为null或引用不同的字节数组,那么任何一种方法都需要返回新值,或者你需要将引用传递给某种"holder",其中包含对字节数组的引用,并且可以在以后从中获取(可能已更改)引用.
换句话说,如果您的方法看起来像这样:
public void doSomething(byte[] data) { for (int i=0; i < data.length; i++) { data[i] = (byte) i; } }
那你很好.如果您的方法如下所示:
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; } }
然后你需要将它改为:
public byte[] createArray(int length) { byte[] data = new byte[length]; for (int i=0; i < data.length; i++) { data[i] = (byte) i; } return data; }
要么:
public class Holder{ public T value; // Use a property in real code! } public void createArray(Holder holder, int length) { holder.value = new byte[length]; for (int i=0; i < length; i++) { holder.value[i] = (byte) i; } }
有关更多详细信息,请参阅参数传递C#和参数传递Java.(前者写的比后者好,我很害怕.有一天我会回来做更新.)
实际上,在Java中,引用是按值传递的.
在这种情况下,引用是一个byte[]
对象.从调用方法可以看到任何影响对象本身的更改.
但是,如果您尝试替换引用(例如,使用) new byte[length]
,则只替换通过pass-by-value获得的引用,因此您不会更改调用方法中的引用.
这是一个关于这个问题的有趣读物:Java是值得传递的Dammit!
这是一个具体的例子:
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); } }
该程序将在方法中创建一个byte
长度数组,该数组将调用该方法,在该方法中创建一个新的长度数组.8
main
modifyArray
byte
16
可能看起来通过byte
在modifyArray
方法中创建一个新数组,byte
返回到该main
方法时数组的长度将是16
,但是,运行此程序会发现一些不同的东西:
Before Method: Length: 8 Method Entry: Length: 8 Method Exit: Length: 16 After Method: Length: 8
byte
从modifyArray
方法返回时数组的长度恢复为8
而不是16
.
这是为什么?
那是因为该main
方法调用了modifyArray
方法并通过使用pass-by-value 将复制的引用new byte[8]
发送给了该方法.然后,该方法通过创建a抛弃复制的引用.到我们离开时,对该引用的引用超出了范围(并最终将被垃圾收集.)但是,该方法仍然引用了它,因为它只发送了复制的引用而不是对引用的实际引用.modifyArray
new byte[16]
modifyArray
new byte[16]
main
new byte[8]
这应该表明Java将使用pass-by-value传递引用.
Java对方法参数使用pass by值.
Primitives(int,boolean等)是Java中的特殊情况..本身不是对象.在这种情况下,将原语(参数)的副本传递给函数.这与通过价值理论很好地吻合.
对于对象,会发生的是对象的引用是按值传递的(引用的副本而不是对象)...但两个引用都指向同一个对象.因此,如果修改方法中的对象参数,则将修改实际对象.
这篇文章应该可以帮到你.. http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.html
至于OP的问题,只需将byte []数组的引用传递给方法.最终结果类似于通过引用传递.如果修改字节数组,调用者将能够在方法执行后看到更改.
更新以平息阻力:) =>表示输出
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 }
次要mods reqd:使用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 }