Java:如何通过引用传递byte ?
您可以使用关键字“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); } }
该程序将在main
方法中创建一个长度为8
的byte
数组,它将调用modifyArray
方法,其中创建一个长度为16
的新byte
数组。
可能看起来通过在modifyArray
方法中创建一个新的byte
数组,返回到main
方法时byte
数组的长度将为16
,但是,运行此程序会显示不同的内容:
Before Method: Length: 8 Method Entry: Length: 8 Method Exit: Length: 16 After Method: Length: 8
从modifyArray
方法返回时, byte
数组的长度恢复为8
而不是16
。
这是为什么?
那是因为main
方法调用了modifyArray
方法,并通过使用pass-by-value 将复制的引用发送到new byte[8]
。 然后, modifyArray
方法通过创建一个new byte[16]
抛弃复制的引用 。 当我们离开modifyArray
,对new byte[16]
的引用超出了范围(最终将被垃圾收集。)但是, main
方法仍然引用了new byte[8]
,因为它只发送了复制参考而不是参考的实际参考。
这应该certificateJava将使用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 []数组的引用传递给方法即可。 最终结果类似于通过引用传递。 如果修改字节数组,调用者将能够看到方法执行后的更改。
更新以平息阻力:) =>表示输出
.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
次要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 }