oxb*_*kes 222

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

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

private void mutate(Object o) { o = "Goodbye"; } //NOT THE SAME o!
Run Code Online (Sandbox Code Playgroud)

将打印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"); }
Run Code Online (Sandbox Code Playgroud)

  • 此外,如果你真的想让人混淆,长度为1的数组可用于创建引用:) (48认同)
  • AtomicReference是一种矫枉过正,你不一定想要内存障碍,它们可能会花费你.由于构造Object时使用的volatile变量,JRuby有性能问题.使用数组作为临时引用的选项对我来说似乎已经足够了,我已经看到它不止一次使用过. (3认同)
  • AtomicReference和相应的类(AtomicInteger)最适合此类操作 (2认同)

Pet*_*Mmm 65

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

没有.

为什么?Java 只有一种向方法传递参数的方式:按值.

注意:

对于原语,这很容易理解:您获得了值的副本.

对于所有其他的,你得到一个引用的副本,这也被称为传递值.

这一切都在这张图片中:

在此输入图像描述

  • 图片坏了. (3认同)

dfa*_*dfa 24

在Java中,语言级别与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();
    }
}
Run Code Online (Sandbox Code Playgroud)

测试用例:

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

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


duf*_*ymo 18

来自James Gosling的"Java编程语言":

"...... Java中只有一个参数传递模式 - 按值传递 - 这样可以保持简单......"

  • @ingyhere:`语言之神的声明应该被宣布为答案:不是真的.尽管Java的创造者认为或相信,但绝对的答案将来自语言规范的引用. (3认同)
  • 语言之神的宣告应该被宣布为答案. (2认同)
  • 事实上它在 [JLS,第 8.4.1 节](http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.1) 中,并且JLS 引用 Gosling 作为第一作者:“当调用方法或构造函数时(第 15.12 节),**实际参数表达式的值会在执行函数体之前初始化新创建的参数变量**,每个声明的类型方法或构造函数。” (2认同)

Mar*_*ell 10

我认为你不能.您最好的选择可能是将要通过"ref"传递到另一个类实例的东西封装,然后传递(外部)类的引用(按值).如果你明白我的意思......

即您的方法更改它传递的对象的内部状态,然后调用者可以看到它.


Nic*_*olt 7

Java总是按值传递.

当你传递一个原语时,它是一个值的副本,当你传递一个对象时,它就是一个引用指针的副本.


小智 5

另一种选择是使用数组,例如 void method(SomeClass[] v) { v[0] = ...; } 但是1)数组必须在调用方法之前初始化,2)仍然不能以这种方式实现例如交换方法...这种方式在JDK中使用,例如在java.util.concurrent.atomic.AtomicMarkableReference.get(boolean[]).