如何通过引用传递基元数据类型?

2022-08-31 20:46:11

如何在java中通过引用传递基元类型?例如,如何使传递给方法的方法可修改?int


答案 1

在Java中,没有办法通过引用直接传递基元。

解决方法是改为传递对包装类实例的引用,然后包装类将基元作为成员字段包含在内。这样的包装类可以非常简单地编写:

public class IntRef { public int value; }

但是一些预先构建的包装类怎么样,这样我们就不必编写自己的包装类了?断续器

Apache commons-lang Mutable* 类:
优点:单线程使用性能良好。完整性。
缺点:引入了第三方库依赖项。没有内置的并发控制。
代表性类可变布尔值可变字节可变双倍、可变浮动可变Int可变长可变对象可变短。

java.util.concurrent.atomic Atomic* 类:
优点:标准 Java (1.5+) API 的一部分。内置并发控制。
缺点:在单线程设置中使用时,性能影响很小。缺少对某些数据类型的直接支持,例如,没有AtomicShort。
代表性类AtomicBooleanAtomicIntegerAtomicLongAtomicReference
注意:正如用户 ColinD 在他的答案中所示,AtomicReference 可以用来近似一些缺失的类,例如 AtomicShort。

长度 1 基元数组
OscarRyz 的答案演示了使用长度 1 数组来“包装”基元值。
优点:写起来快。高性能。无需第三方库。
缺点:有点脏。没有内置的并发控制。导致代码不能(清楚地)自我记录:方法签名中的数组是否存在,以便我可以传递多个值?还是作为逐引用传递仿真的基架?

另请参阅
StackOverflow 问题“Java 中的可变布尔字段”的答案

我的观点
在Java中,您应该努力谨慎地使用上述方法,或者根本不使用。在 C 中,通常使用函数的返回值来中继状态代码(SUCCESS/FAILURE),而函数的实际输出则通过一个或多个 out 参数进行中继。在 Java 中,最好使用异常而不是返回代码。这释放了方法返回值,用于携带实际的方法输出 - 大多数Java程序员发现这种设计模式比out参数更自然。


答案 2

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