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方法中创建一个长度为8byte数组,它将调用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 }