繁体   English   中英

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

[英]Can I pass parameters by reference in Java?

我想要类似于C#ref关键字的语义。

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"); }

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

不。

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

笔记:

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

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

这一切都在这张照片中:

在此处输入图片说明

在 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();
    }
}

测试用例:

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

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

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

“……Java 中只有一种参数传递模式——按值传递——这让事情变得简单……”

我不认为你可以。 您最好的选择可能是将您想要“通过引用”传递给另一个类实例的内容封装起来,并传递(外部)类的引用(通过值)。 如果你明白我的意思...

即你的方法改变了它传递的对象的内部状态,然后调用者可以看到它。

Java 总是按值传递。

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

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

查看我的回复: 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);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM