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

时间:2009-07-01 11:59:39

标签: c# java reference

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

8 个答案:

答案 0 :(得分:221)

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

答案 1 :(得分:65)

  

我可以通过引用传递参数吗?   爪哇?

没有

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

注意:

对于原语,这很容易理解:你得到了值的副本。

对于所有其他人,你会得到一份参考文献,这也被称为传递值。

这一切都在这张照片中:

enter image description here

答案 2 :(得分:23)

在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"

答案 3 :(得分:18)

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

  

“... Java中只有一个参数传递模式 - 按值传递 - 这使事情变得简单。   ..“

答案 4 :(得分:10)

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

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

答案 5 :(得分:7)

Java总是按值传递。

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

答案 6 :(得分:4)

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

答案 7 :(得分:0)

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