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

Java 如何通过引用传递基元数据类型?,java,pass-by-reference,primitive-types,Java,Pass By Reference,Primitive Types,如何在java中通过引用传递基元类型?例如,如何使传递给方法的int可修改?这在Java中是不可能的Java中没有任何东西是通过引用传递的。都是按值传递的 编辑:基本体和对象类型都按值传递。您永远不能更改传递的值/引用,而期望原始值/引用发生更改。例如: String a; int b; doSomething(a, b); ... public void doSomething(String myA, int myB) { // whatever I do to "myA" and

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

这在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"
}
绕过这个障碍的唯一方法,不管它是原语还是引用,都是传递一个容器对象,或者使用返回值

持证人:

有返回值


将具有该值的对象作为字段传递。

一个选项是使用java.lang.Integer之类的类,这样就根本不传递原语

另一方面,您可以使用如下代码:

int a = 5;
a = func(a);

并让func返回修改后的值。

您不能。但是您可以返回一个整数,它是一个修改后的值

int i = 0;
i = doSomething(i);

如果您要传递多个变量,您可能希望创建一个(专门包含一组可传递给类的变量的类)。

传递一个
原子整数
原子布尔
,等等。并不是每个基元类型都有一个,但是如果需要,您也可以使用
AtomicReference


注意:在Java中很少需要这样做。当你想做这件事时,我建议你重新思考你想做的事情,看看你是否能用其他方法来做(使用一个返回
int
,比如说…最好的方法是根据不同的情况而不同)。

在Java中没有直接通过引用传递原语的方法

一种解决方法是将引用传递给包装类的实例,然后包装类将原语作为成员字段包含。这样的包装器类可以非常简单地为自己编写:

public class IntRef { public int value; }
但是一些预构建的包装器类怎么样,这样我们就不必编写自己的包装器类了?好:

Apache可变*类:
优点:单线程使用性能良好。完整性。
缺点:引入了第三方库依赖关系。没有内置的并发控制。
代表类:

原子*类:
优点:是标准Java(1.5+)API的一部分。内置并发控制。
缺点:在单线程设置中使用时性能影响小。缺少对某些数据类型的直接支持,例如没有AtomicShort。
代表类:、和。
注意:作为用户ColinD,AtomicReference可用于近似某些缺少的类,例如AtomicShort

长度1基元数组
演示如何使用长度为1的数组“包装”基元值。
优点:书写速度快。表演。不需要第三方库。
缺点:有点脏。没有内置的并发控制。导致代码无法(清楚地)自我记录:方法签名中的数组是否存在,以便我可以传递多个值?或者它在这里作为通过引用模拟的脚手架

另请参见
问题“”的答案

我的意见

在Java中,您应该尽量少用或根本不用上述方法。在C语言中,通常使用函数的返回值来中继状态代码(成功/失败),而函数的实际输出通过一个或多个输出参数中继。在Java中,最好使用异常而不是返回代码。这释放了方法返回值,用于承载实际的方法输出——大多数Java程序员发现这是一种比输出参数更自然的设计模式。

这在Java中是不可能的,您也可以将其包装在单个元素数组中

void demo() { 
    int [] a = { 0 };
    increment ( a ) 
}
void increment( int [] v ) { 
     v[0]++;
}

但总有更好的选择

整数和朋友是不可变的。java.util.concurrent.AtomicInteger和朋友是可变的。我见过的另一种(粗略的)选择是使用一个1元素数组。这是实现它的一种方法,只需一个值+1尽管我认为这与仅使用包装器/持有者对象相比可能是一个沉重的负担。如果您仅使用
set(int)
对其进行变异,我认为不会有任何值得担心的性能影响。。。在我看来,创建您自己的可变包装器来实现这一点(或者导入commons lang…)将是一种更糟糕的冒犯。另外,我希望这不是经常做的,因为我认为在很多情况下这不是真的需要。同意导入commons lang是个坏主意。我猜OP是一个C程序员,他想继续使用相同的范例,这会导致理解C程序的大多数复杂性,所以我想他会经常使用这种“通过引用传递原语”的解决方案;在Java中,传递C风格的可变原语几乎总是错误的。它所做的只是使代码变得不必要的复杂。“Correct”是一个布尔条件,不允许使用程度或种类的修饰符。@tchrist:您可以在不回答问题的情况下做出正确的陈述。我可以说“1+1=2”,这是正确的,但没有回答问题。这里的原始答案更接近于回答这个问题,但仍然没有提供任何对提问者实际有用的答案。原子学非常方便地将计数器传递给一个被多次调用的函数,但是,特别是如果函数中计数器的增加是有条件的,但不增加不一定意味着失败。无论如何,谢谢你的回答。这非常有用。我认为这也适用于
Integer
public class IntRef { public int value; }
void demo() { 
    int [] a = { 0 };
    increment ( a ) 
}
void increment( int [] v ) { 
     v[0]++;
}