2

我对 Java 还很陌生,最近我正在阅读一些关于 Java 是按值传递的材料。在我自己运行测试之前,我已经阅读了这个问题这个博客。

现在,根据我的阅读和快速测试,我发现有两种方法可以更改对象引用中包含的变量。以下哪种方法是更好或更安全的方法?这两种方法有什么明显的问题吗?

这两个都打印出“iArr[0] = 45”。

方法一:

public static void main(String args[] ){
   int[] iArr = {1};
   method(iArr) ;
   System.out.println( "iArr[0] = " + iArr [0] ) ;
}
public static void method(int[] n ) { 
    n [0] = 45 ;
}

方法二:

public static void main(String args[] )
{
   int[] iArr = {1};
   iArr = method(iArr) ;
   System.out.println( "iArr[0] = " + iArr [0] ) ;
}
public static int[] method(int[] n ) { 
    n [0] = 45 ;
    return n;
}
4

2 回答 2

2

第二种方法开辟了别名的可能性。

int[] n = {1};
int[] j;

j = method(n);
j[0] = 342;
System.out.println("iArr[0] = " + n[0]);
System.out.println("iArr[0] = " + j[0]);

将打印出:

iArr[0] = 342
iArr[0] = 342

因此,在这种情况下,我会选择第一种方法。您只想更改数组,无需返回引用。如果需要,也可以轻松创建自己的别名。从第二种方法中也不清楚您是否更改了实际参数值,我认为这是非常糟糕的做法。

于 2012-06-21T23:17:11.357 回答
2

我发现这两种方法都不理想,因为它们都会引起相同的副作用

也就是说,它们是相同的,但是第二种方法返回了修改后的对象:第二种方法仍然修改了传入的数组对象!iArr示例代码中 #2 的返回值的重新赋值对修改的对象没有影响!请记住,Java 使用Call-By-Object-Sharing语义(对于引用类型);返回值与此行为无关。

我实际上真的不喜欢方法#2,因为它“隐藏”了这个事实(我看着签名并想“哦,我得到了一个的数组对象!”),而方法#1“它是脏活”,但我可以告诉从void返回类型很快。(在某些高级外壳中,“链接”可能很有用;这不是其中之一。)

这是一个不会引起副作用的简单版本:(我建议尽量减少副作用,因为它通常使代码更容易推理和调试。)

public static void main(String args[] )
{
   int[] iArr = {1};
   int[] newArr = method(iArr) ;
   System.out.println( "iArr[0] = " + iArr [0] ) ;
   // This is different here, but it would "be the same" in the 
   // 2nd-case example in the post.
   System.out.println( "newArr[0] = " + newArr [0] ) ;
}
public static int[] method(int[] n ) {
    // This is a silly stub method, n would be presumably used.
    int[] x = new int[1];
    x[0] = 45; // modifying a DIFFERENT object
    return x;  // returning the NEW object
}
于 2012-06-21T23:22:12.480 回答