【发布时间】:2011-05-18 04:47:27
【问题描述】:
如何在 java 中通过引用传递原始类型?例如,如何使 int 传递给可修改的方法?
【问题讨论】:
-
我认为这也适用于
Integer
标签: java pass-by-reference primitive-types
如何在 java 中通过引用传递原始类型?例如,如何使 int 传递给可修改的方法?
【问题讨论】:
Integer
标签: java pass-by-reference primitive-types
在 Java 中没有直接通过引用传递原语的方法。
一种解决方法是将引用传递给包装类的实例,然后将原语作为成员字段包含在内。为自己编写这样一个包装类可能非常简单:
public class IntRef { public int value; }
但是一些预先构建的包装类怎么样,这样我们就不必自己编写了?好的:
Apache commons-lang Mutable* 类:
优势:单线程使用性能好。完整性。
缺点:引入了第三方库依赖项。没有内置的并发控制。
代表类:MutableBoolean、MutableByte、MutableDouble、MutableFloat、MutableInt、MutableLong、MutableObject、MutableShort。
java.util.concurrent.atomic Atomic* 类:
优势:标准 Java (1.5+) API 的一部分。内置并发控制。
缺点:在单线程设置中使用时性能损失很小。缺少对某些数据类型的直接支持,例如没有 AtomicShort。
代表类:AtomicBoolean、AtomicInteger、AtomicLong 和 AtomicReference。
注意:作为用户 ColinD shows in his answer,AtomicReference 可用于近似一些缺失的类,例如原子短。
长度为 1 的原始数组
OscarRyz's answer 演示了使用长度为 1 的数组来“包装”原始值。
优点:写起来快。高性能。不需要第三方库。
缺点:有点脏。没有内置的并发控制。导致代码不(清楚地)自记录:方法签名中的数组是否在那里,所以我可以传递多个值?还是在这里作为传递引用仿真的脚手架?
另请参阅
StackOverflow 问题“Mutable boolean field in Java”的答案。
我的意见
在 Java 中,您应该尽量少用或根本不使用上述方法。在 C 语言中,通常使用函数的返回值来传递状态代码(SUCCESS/FAILURE),而函数的实际输出通过一个或多个输出参数传递。在 Java 中,最好使用异常而不是返回码。这释放了用于承载实际方法输出的方法返回值——大多数 Java 程序员发现这种设计模式比输出参数更自然。
【讨论】:
java 中没有任何东西是通过引用传递的。都是按值传递的。
编辑:原语和对象类型都是按值传递的。您永远不能更改传递的值/引用并期望原始值/引用发生变化。示例:
String a;
int b;
doSomething(a, b);
...
public void doSomething(String myA, int myB) {
// whatever I do to "myA" and "myB" here will never ever ever change
// the "a" and "b"
}
绕过这个障碍的唯一方法是传递一个容器对象,或者使用返回值。
带支架:
private class MyStringHolder {
String a;
MyStringHolder(String a) {
this.a = a;
}
}
MyStringHolder holdA = new MyStringHolder("something");
public void doSomething(MyStringHolder holder) {
// alter holder.a here and it changes.
}
有返回值
int b = 42;
b = doSomething(b);
public int doSomething(int b) {
return b + 1;
}
【讨论】:
改为传递AtomicInteger、AtomicBoolean 等。并非每种原始类型都有一个,但如果需要,您也可以使用 AtomicReference<Short>。
请注意:在 Java 中应该很少需要做这样的事情。当您想这样做时,我建议您重新考虑您正在尝试做的事情,看看您是否不能以其他方式做到这一点(使用返回int的方法,比如说......什么是最好的要做的事情会因情况而异)。
【讨论】:
set(int) 对其进行变异,我认为不会有任何值得担心的性能影响...创建自己的可变包装器来执行此操作(或导入 commons-lang ,就此而言...)在我看来将是更糟糕的冒犯。另外,我希望不要经常这样做,因为我认为在很多情况下都不需要这样做。
这在 Java 中是不可能的,作为替代方案,您可以将其包装在单个元素数组中。
void demo() {
int [] a = { 0 };
increment ( a )
}
void increment( int [] v ) {
v[0]++;
}
但总有更好的选择。
【讨论】:
你不能。但是你可以返回一个整数,它是一个修改后的值
int i = 0;
i = doSomething(i);
如果您要传递多个,您可能希望创建一个Data Transfer Object(一个专门包含一组可以传递给类的变量的类)。
【讨论】:
将具有该值的对象作为字段传递。
【讨论】:
这在 Java 中是不可能的
【讨论】:
一种选择是使用 java.lang.Integer 之类的类,那么您根本不会传递原语。
另一方面,您可以使用如下代码:
int a = 5;
a = func(a);
并让 func 返回修改后的值。
【讨论】: