Stu*_*ent 111 java pass-by-reference
这个Java代码:
public class XYZ {
public static void main(){
int toyNumber = 5;
XYZ temp = new XYZ();
temp.play(toyNumber);
System.out.println("Toy number in main " + toyNumber);
}
void play(int toyNumber){
System.out.println("Toy number in play " + toyNumber);
toyNumber++;
System.out.println("Toy number in play after increement " + toyNumber);
}
}
Run Code Online (Sandbox Code Playgroud)
将输出:
Toy number in play 5 Toy number in play after increement 6 Toy number in main 5
在C++中,我可以通过toyNumber
引用传递变量以避免阴影,即创建同一个变量的副本,如下所示:
void main(){
int toyNumber = 5;
play(toyNumber);
cout << "Toy number in main " << toyNumber << endl;
}
void play(int &toyNumber){
cout << "Toy number in play " << toyNumber << endl;
toyNumber++;
cout << "Toy number in play after increement " << toyNumber << endl;
}
Run Code Online (Sandbox Code Playgroud)
并且C++输出将是这样的:
Toy number in play 5 Toy number in play after increement 6 Toy number in main 6
我的问题是 - 考虑到Java是通过值传递而不是通过引用传递,Java中的等效代码与C++代码获得相同的输出是什么?
las*_*owh 169
你有几个选择.最有意义的那个取决于你想要做什么.
选择1:使toyNumber成为类中的公共成员变量
class MyToy {
public int toyNumber;
}
Run Code Online (Sandbox Code Playgroud)
然后将对MyToy的引用传递给您的方法.
void play(MyToy toy){
System.out.println("Toy number in play " + toy.toyNumber);
toy.toyNumber++;
System.out.println("Toy number in play after increement " + toy.toyNumber);
}
Run Code Online (Sandbox Code Playgroud)
选择2:返回值而不是通过引用传递
int play(int toyNumber){
System.out.println("Toy number in play " + toyNumber);
toyNumber++;
System.out.println("Toy number in play after increement " + toyNumber);
return toyNumber
}
Run Code Online (Sandbox Code Playgroud)
这个选择需要对main中的callsite进行少量更改才能读取toyNumber = temp.play(toyNumber);
.
选择3:使它成为一个类或静态变量
如果这两个函数是同一个类或类实例上的方法,则可以将toyNumber转换为类成员变量.
选择4:创建int类型的单个元素数组并传递它
这被认为是hack,但有时用于从内联类调用返回值.
void play(int [] toyNumber){
System.out.println("Toy number in play " + toyNumber[0]);
toyNumber[0]++;
System.out.println("Toy number in play after increement " + toyNumber[0]);
}
Run Code Online (Sandbox Code Playgroud)
Ker*_*ğan 29
Java不是通过引用调用它只是按值调用
但是对象类型的所有变量实际上都是指针.
因此,如果您使用Mutable对象,您将看到所需的行为
public class XYZ {
public static void main(String[] arg) {
StringBuilder toyNumber = new StringBuilder("5");
play(toyNumber);
System.out.println("Toy number in main " + toyNumber);
}
private static void play(StringBuilder toyNumber) {
System.out.println("Toy number in play " + toyNumber);
toyNumber.append(" + 1");
System.out.println("Toy number in play after increement " + toyNumber);
}
}
Run Code Online (Sandbox Code Playgroud)
输出此代码:
run:
Toy number in play 5
Toy number in play after increement 5 + 1
Toy number in main 5 + 1
BUILD SUCCESSFUL (total time: 0 seconds)
Run Code Online (Sandbox Code Playgroud)
您也可以在标准库中看到此行为.例如Collections.sort(); Collections.shuffle(); 这些方法不返回新列表,而是修改它的参数对象.
List<Integer> mutableList = new ArrayList<Integer>();
mutableList.add(1);
mutableList.add(2);
mutableList.add(3);
mutableList.add(4);
mutableList.add(5);
System.out.println(mutableList);
Collections.shuffle(mutableList);
System.out.println(mutableList);
Collections.sort(mutableList);
System.out.println(mutableList);
Run Code Online (Sandbox Code Playgroud)
输出此代码:
run:
[1, 2, 3, 4, 5]
[3, 4, 1, 5, 2]
[1, 2, 3, 4, 5]
BUILD SUCCESSFUL (total time: 0 seconds)
Run Code Online (Sandbox Code Playgroud)
Ing*_*ngo 18
做一个
class PassMeByRef { public int theValue; }
Run Code Online (Sandbox Code Playgroud)
然后将引用传递给它的实例.请注意,最好避免通过其参数改变状态的方法,尤其是在并行代码中.
Ern*_*ill 10
您不能通过Java中的引用传递基元.当然,对象类型的所有变量实际上都是指针,但我们将它们称为"引用",它们也总是按值传递.
在您确实需要按值传递基元的情况下,人们有时会做的是将参数声明为基本类型的数组,然后将单元素数组作为参数传递.所以你传递一个引用int [1],在方法中,你可以改变数组的内容.
小智 10
对于快速解决方案,您可以使用AtomicInteger或任何原子变量,这些变量将允许您使用内置方法更改方法内的值.这是示例代码:
import java.util.concurrent.atomic.AtomicInteger;
public class PrimitivePassByReferenceSample {
/**
* @param args
*/
public static void main(String[] args) {
AtomicInteger myNumber = new AtomicInteger(0);
System.out.println("MyNumber before method Call:" + myNumber.get());
PrimitivePassByReferenceSample temp = new PrimitivePassByReferenceSample() ;
temp.changeMyNumber(myNumber);
System.out.println("MyNumber After method Call:" + myNumber.get());
}
void changeMyNumber(AtomicInteger myNumber) {
myNumber.getAndSet(100);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
MyNumber before method Call:0
MyNumber After method Call:100
Run Code Online (Sandbox Code Playgroud)