我可以在 Java 中通过引用传递参数吗?

我希望语义类似于 C#ref关键字。

151605 次浏览

Java 之所以令人困惑,是因为 一切都是通过值传递的。然而,对于参数 参考类型(即不是基元类型的参数) ,它是通过值传递的 引用本身,因此它是通过引用传递的 出现了(人们经常声称它是)。情况并非如此,如下所示:

Object o = "Hello";
mutate(o)
System.out.println(o);


private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!

将向控制台打印 Hello。如果您希望上面的代码打印 Goodbye,可以按以下方式对 使用明确的引用进行选择:

AtomicReference<Object> ref = new AtomicReference<Object>("Hello");
mutate(ref);
System.out.println(ref.get()); //Goodbye!


private void mutate(AtomicReference<Object> ref) { ref.set("Goodbye"); }

我觉得你做不到。您最好的选择可能是封装您想要传递“ by ref”到另一个类实例的内容,并传递(外部)类的引用(通过值)。如果你明白我的意思..。

也就是说,你的方法改变了它所传递的对象的内部状态,这对于调用者来说是可见的。

在 Java 中,在语言级别上没有类似于 裁判的东西

出于好奇,您可以在 Java 中实现类似于 ref 的语义,只需将您的对象包装在一个可变的类中:

public class Ref<T> {


private T value;


public Ref(T value) {
this.value = value;
}


public T get() {
return value;
}


public void set(T anotherValue) {
value = anotherValue;
}


@Override
public String toString() {
return value.toString();
}


@Override
public boolean equals(Object obj) {
return value.equals(obj);
}


@Override
public int hashCode() {
return value.hashCode();
}
}

测试用例:

public void changeRef(Ref<String> ref) {
ref.set("bbb");
}


// ...
Ref<String> ref = new Ref<String>("aaa");
changeRef(ref);
System.out.println(ref); // prints "bbb"

中通过引用传递参数 爪哇?

没有。

为什么? Java 使用 只有一个模式将参数传递给方法: by value。

注:

对于原语,这很容易理解: 您将获得值的一个副本。

对于所有其他的引用,您将获得引用的一个副本,这也称为通过值传递。

这一切都在这张图片中:

enter image description here

Java 总是通过值传递。

当你传递一个基元时,它是值的一个副本,当你传递一个对象时,它是引用指针的一个副本。

来自 James Gosling 的“ Java 编程语言”:

在 Java 中只有一种参数传递模式——通过值传递——这使事情变得简单。 .."

另一个选择是使用数组,例如。 void method(SomeClass[] v) { v[0] = ...; } 但是1)数组必须在调用方法之前被初始化,2)仍然不能用这种方式实现,例如交换方法..。 这种方法在 JDK 也有使用,例如 ABc0。

看看我的回答: http://stackoverflow.com/a/9324155/1676736

在那里,我使用了一个简单版本的包装器类思想。 我不喜欢把 setter/getter 作为标准。当没有理由埋葬一块地时,我会让它“公开”。尤其是在这种情况下。

但是,除了原语或多参数/类型返回值之外,这种方法对所有情况都适用:

public class Ref<T> {
public T val;
}

不过,我想您可以添加更多的类型参数。但我认为,创建一个适合目的的内部静态类会更容易:

public static class MyReturn {
public String name;
public int age;
public double salary;
}

当你因为其他原因不需要它的时候,它就会派上用场。

MyReturn mRtn = new MyReturn();


public void myMethod(final MyReturn mRtn){
mRtn.name = "Fred Smith";
mRtn.age = 32;
mRtn.salary = 100000.00;
}


System.out.println(mRtn.name + " " +mRtn.age + ": $" + mRtn.salary);