如何在Java中通过引用传递数组?例如,我需要对数组A和B执行一些操作,并填充应该可供调用者使用的数组C.
public boolean Operate(int[] A, int[] B, int[] C)
{
//Write into the empty array C by manipulating values of A and B and it should be accessible to caller
}
I read与C#不同,Java中不存在引用传递。在这种情况下,最好的方法是什么。
答案 0 :(得分:3)
你得到的术语'通过引用传递'与'传递(对象的引用)按值'(其中是什么Java和C#,没有out / ref做什么)。在上文中,如果A,B或C的内容被改变,则它们被改变,因为当它们被传递给该方法时没有新的对象被创建/克隆/重复。在C#中,'ref'和'out'如何使用'按引用传递'。请注意,当使用'按引用传递'时,分配给变量会更改调用者传入的变量值(这在Java中是不可能的)。< / p>
请参阅Wiki: Evaluation Strategies。
编辑:如果您真的希望遵循这种方法,请记住调用约定并不表示对象的可变性。请考虑以下事项:
void merge(int[] A, int[] B, int[][] C) {
int[] t = internalMerge(A, B);
C[0] = t;
}
int[][] icky = new int[1][0];
merge(..., ..., icky);
int[] r = icky[1];
但是,我会简单地构建代码。没有理由使用这种方法,它引入了更多的副作用和状态突变。如您所见,上面的代码已经引入了运行时错误。正如其他人所建议的那样,为什么不简单地返回更合适的值?
答案 1 :(得分:3)
在Java中,数组是引用类型,而不是 value 类型。这意味着数组变量只将引用存储到实际数组中。
例如,请考虑以下代码:
int[] numbers = new int[3];
在此示例中,numbers
是3个int
s数组的引用。这可以说明如下:
Java Stack | Java Heap | | Array of ints: +---------+ | +---+---+---+ | numbers |-------------->| 0 | 0 | 0 | +---------+ | +---+---+---+ | 0 1 2
现在假设您有这样的方法:
public void compute(int[] someValues) {
someValues[2] = 78;
}
假设您使用numbers
变量作为参数调用此方法:
int[] numbers = new int[3];
compure(numbers);
在这种情况下,numbers
引用将按值传递给compute
。因此,someValues
是numbers
引用的副本(不是numbers
引用的数组的副本)。因此,它看起来像这样:
Java Stack | Java Heap | | Array of ints: +---------+ | +---+---+---+ | numbers |-------------->| 0 | 0 | 0 | +---------+ | --> +---+---+---+ | / 0 1 2 +------------+ | / | someValues |-----/ +------------+ |
compute
返回后,它将如下所示:
Java Stack | Java Heap | | Array of ints: +---------+ | +---+---+----+ | numbers |-------------->| 0 | 0 | 78 | +---------+ | --> +---+---+----+ | / 0 1 2 +------------+ | / | someValues |-----/ +------------+ |
numbers[2]
将等于someValues[2]
因为numbers
和someValues
引用相同的数组。
叹息,自从我开始写答案以来,似乎已经回答了类似问题。希望ASCII图表值得保留!
答案 2 :(得分:2)
正如你所说,在Java中不可能通过引用传递参数。
以下是您的问题的一些解决方法:
C
变量。 null
与否)以替换布尔值。List<Integer>
传递给该函数,然后将其转换为数组。您还可以创建一个ReferenceArgument<T>
类,可以通过以下方式实现:
public final class ReferenceArgument<T> {
public T obj = null;
// You could also make the field private and use getter/setter methods.
}
我会建议不要这样做 - 但是我相信它不适用于数组(它们与泛型不能很好地混合) - 并且它会包含原始类型,这有点笨拙。
答案 3 :(得分:1)
我假设你从方法中返回一个布尔值来表示成功或失败。
您可以从函数返回数组C,而不是返回布尔值。如果C为null,则表示函数失败。如果没有,则功能成功。
答案 4 :(得分:1)
所有参数都按值传递。但是在您的情况下,您有一个通过值传递的引用(而不是数组中的数据)。这意味着引用被复制并且不能更改,但可以更改引用的数据。 e.g。
// doesn't work because it doesn't change the caller's x and y
public static void swapReferences(int[] x, int[] y) {
int[] t = x;
x = y;
y = t;
}
int[] x, y;
swapReferences(x, y);
// x and y are unchanged and point to the same arrays with the same data.
// swap the contents
public static void swapContents(int[] x, int[] y) {
int[] t = new int[x.length];
System.arraycopy(x,0,t,0,x.length);
System.arraycopy(y,0,x,0,x.length);
System.arraycopy(t,0,y,0,x.length);
}
swapContents(x, y);
// x and y are unchanged but the data they refer to has been swapped.
答案 5 :(得分:-1)
我相信你对术语有点困惑。别担心。在java中,除了基元之外的所有内容都通过引用传递如果是您的阵列,您可以在您的方法中填写它,并且调用者可以看到更改。
答案 6 :(得分:-1)
您总是在java中通过引用传递数组。唯一没有通过引用传递的对象(但是通过值传递)是基元,int, long, boolean, double, float
等。其他所有对象都是一个对象并通过引用传递。所以你的代码会正常工作。
编辑:我谦卑地承认我的愚蠢错误。您始终在java中通过值传递。但是对象总是以引用作为值传递。