【发布时间】:2020-09-08 19:28:53
【问题描述】:
我想要类似于 C# 的 ref 关键字的语义。
【问题讨论】:
-
萨拉姆。这个答案解决了我的问题:http://stackoverflow.com/a/9324155/1676736
我想要类似于 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 中,在语言级别上没有类似于 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"
【讨论】:
AtomicReference(对于非原始人)?还是AtomicSomething(例如:AtomicBoolean)用于基元?
int 而不是Integer、bool 而不是Boolean 等真的足够重要吗?也就是说,包装类(如果您担心语法,它们会自动解包)不起作用?
我可以通过引用传递参数吗 爪哇?
没有。
为什么? Java只有一种向方法传递参数的模式:按值。
注意:
对于原语来说,这很容易理解:你会得到一个值的副本。
对于所有其他人,您将获得引用的副本,这也称为按值传递。
这一切都在这张照片中:
【讨论】:
Java 总是按值传递。
当你传递一个原语时,它是值的副本,当你传递一个对象时,它是引用指针的副本。
【讨论】:
来自“Java 编程语言”中的 James Gosling:
"...Java 中只有一种参数传递模式——按值传递——这让事情变得简单。 ..”
【讨论】:
The pronouncement of the language god should be declared the answer :不是真的。不管 Java 的创造者怎么想或相信什么,绝对的答案将来自语言规范的引用。
另一种选择是使用数组,例如
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);
【讨论】: