Java:如何通过引用传递byte[]?

2022-09-02 00:06:45

您可以使用关键字“ref”在 .NET 中执行此操作。在Java中有什么办法可以做到这一点吗?


答案 1

你在你的方法中做了什么?如果只是填充现有数组,则不需要按引用传递语义 - 无论是在 .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<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;
    }
}

有关更多详细信息,请阅读 C# 中的参数传递Java 中的参数传递。(恐怕前者比后者写得更好。有一天我会开始做一个更新。


答案 2

实际上,在Java中,引用是按值传递的

在本例中,引用是一个对象。任何影响对象本身的更改都将从调用方方法中看到。byte[]

但是,如果尝试替换引用(例如使用 ),则只会替换通过按值传递获得的引用,因此不会更改调用方方法中的引用。new byte[length]

这里有一个关于这个问题的有趣读物:Java是按值传递的该死的!


下面是一个具体示例:

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);
    }
}

此程序将在方法中创建一个长度数组,该数组将调用该方法,并在其中创建一个新的长度数组。byte8mainmodifyArraybyte16

通过在方法中创建新数组,似乎返回该方法时数组的长度将为 ,但是,运行此程序会显示一些不同的东西:bytemodifyArraybytemain16

Before Method: Length: 8
Method Entry:  Length: 8
Method Exit:   Length: 16
After Method:  Length: 8

从该方法返回时,数组的长度将恢复为 而不是 。bytemodifyArray816

为什么?

这是因为该方法调用了该方法,并使用传递值发送了对新字节[8]的复制引用。然后,该方法通过创建一个新字节来丢弃复制的引用[16]。当我们离开时,对 的引用已经超出了范围(最终将被垃圾回收)。但是,该方法仍然具有对 的引用,因为它仅发送复制的引用,而不是对引用的实际引用。mainmodifyArraymodifyArraymodifyArraynew byte[16]mainnew byte[8]

这应该证明Java将使用按值传递引用。