简体   繁体   English

如何通过引用传递原始数据类型?

[英]How do I pass a primitive data type by reference?

How can I pass a primitive type by reference in java? 如何在java中通过引用传递原始类型? For instance, how do I make an int passed to a method modifiable? 例如,如何将int传递给可修改的方法?

There isn't a way to pass a primitive directly by reference in Java. 没有办法通过Java中的引用直接传递原语。

A workaround is to instead pass a reference to an instance of a wrapper class, which then contains the primitive as a member field. 解决方法是将引用传递给包装类的实例,然后将包含原语作为成员字段。 Such a wrapper class could be extremely simple to write for yourself: 这样的包装类可以非常简单地为自己编写:

public class IntRef { public int value; }

But how about some pre-built wrapper classes, so we don't have to write our own? 但是一些预先构建的包装类怎么样,所以我们不必编写自己的包装类? OK: 好:

The Apache commons-lang Mutable* classes: Apache commons-lang Mutable *类:
Advantages : Good performance for single threaded use. 优点 :单线程使用性能良好。 Completeness. 完整性。
Disadvantages : Introduces a third-party library dependency. 缺点 :引入第三方库依赖项。 No built-in concurrency controls. 没有内置的并发控件。
Representative classes : MutableBoolean , MutableByte , MutableDouble , MutableFloat , MutableInt , MutableLong , MutableObject , MutableShort . 代表类MutableBooleanMutableByteMutableDoubleMutableFloatMutableIntMutableLongMutableObjectMutableShort

The java.util.concurrent.atomic Atomic* classes: java.util.concurrent.atomic Atomic *类:
Advantages : Part of the standard Java (1.5+) API. 优点 :标准Java(1.5+)API的一部分。 Built-in concurrency controls. 内置并发控件。
Disadvantages : Small performance hit when used in a single-threaded setting. 缺点 :在单线程设置中使用时性能损失很小。 Missing direct support for some datatypes, eg there is no AtomicShort. 缺少对某些数据类型的直接支持,例如没有AtomicShort。
Representative classes : AtomicBoolean , AtomicInteger , AtomicLong , and AtomicReference . 代表类AtomicBooleanAtomicIntegerAtomicLongAtomicReference
Note : As user ColinD shows in his answer , AtomicReference can be used to approximate some of the missing classes, eg AtomicShort. 注意 :正如用户ColinD 在他的回答中所示 ,AtomicReference可用于估计一些缺失的类,例如AtomicShort。

Length 1 primitive array 长度为1的原始数组
OscarRyz's answer demonstrates using a length 1 array to "wrap" a primitive value. OscarRyz的答案演示了使用长度为1的数组来“包装”原始值。
Advantages : Quick to write. 优点 :快速编写。 Performant. 高性能。 No 3rd party library necessary. 不需要第三方图书馆。
Disadvantages : A little dirty. 缺点 :有点脏。 No built-in concurrency controls. 没有内置的并发控件。 Results in code that does not (clearly) self-document: is the array in the method signature there so I can pass multiple values? 代码中没有(明确地)自我文档的结果:是方法签名中的数组,所以我可以传递多个值? Or is it here as scaffolding for pass-by-reference emulation? 或者它是否作为脚手架传递引用仿真?

Also see 另见
The answers to StackOverflow question " Mutable boolean field in Java ". StackOverflow的答案问题“ Java中的可变布尔字段 ”。

My Opinion 我的看法
In Java, you should strive to use the above approaches sparingly or not at all. 在Java中,您应该尽量少用或不用上述方法。 In C it is common to use a function's return value to relay a status code (SUCCESS/FAILURE), while a function's actual output is relayed via one or more out-parameters. 在C中,通常使用函数的返回值来中继状态代码(SUCCESS / FAILURE),而函数的实际输出通过一个或多个输出参数进行中继。 In Java, it is best to use Exceptions instead of return codes. 在Java中,最好使用Exceptions而不是返回代码。 This frees up method return values to be used for carrying the actual method output -- a design pattern which most Java programmers find to be more natural than out-parameters. 这释放了用于携带实际方法输出的方法返回值 - 大多数Java程序员发现的设计模式比out参数更自然。

Nothing in java is passed by reference. java中没有任何内容通过引用传递。 It's all passed by value. 这一切都是通过价值传递的。

Edit: Both primitives and object types are passed by value. 编辑:原语和对象类型都按值传递。 You can never alter the passed value/reference and expect the originating value/reference to change. 您永远不能更改传递的值/引用,并期望原始值/引用发生更改。 Example: 例:

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

The only way to get around this hurdle, regardless of it being a primitive or reference, is to pass a container object, or use the return value. 绕过这个障碍的唯一方法是传递容器对象,或者使用返回值,而不管它是原始的还是引用。

With a holder: 持有人:

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

With return value 具有返回值

int b = 42;
b = doSomething(b);

public int doSomething(int b) {
  return b + 1;
}

Pass an AtomicInteger , AtomicBoolean , etc. instead. AtomicBoolean ,传递一个AtomicIntegerAtomicBoolean等。 There isn't one for every primitive type, but you can use, say, an AtomicReference<Short> if necessary too. 每种原始类型都没有,但如果需要,您可以使用AtomicReference<Short>

Do note: there should very rarely be a need to do something like this in Java. 请注意:在Java中很少需要做这样的事情。 When you want to do it, I'd recommend rethinking what you're trying to do and seeing if you can't do it some other way (using a method that returns an int , say... what exactly the best thing to do is will vary from situation to situation). 当你想要这样做的时候,我建议你重新考虑你想要做的事情,看看你是不是可以用其他方式去做(使用返回int的方法,比如说...究竟最好的是什么做的将因情况而异)。

That's not possible in Java, as an alternative you can wrap it in a single element array. 这在Java中是不可能的,作为替代方案,您可以将其包装在单个元素数组中。

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

But there are always better options. 但总有更好的选择。

You can't. 你不能。 But you can return an integer which is a modified value 但是您可以返回一个修改后的值的整数

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

If you are passing in more than one you may wish to create a Data Transfer Object (a class specifically to contain a set of variables which can be passed to classes). 如果您传递的不止一个,您可能希望创建一个数据传输对象 (一个专门用于包含一组可以传递给类的变量的类)。

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

这在Java中是不可能的

One option is to use classes like java.lang.Integer, then you're not passing a primitive at all. 一种选择是使用像java.lang.Integer这样的类,然后根本不传递基元。

On the other hand, you can just use code like: 另一方面,您可以使用以下代码:

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

and have func return the modified value. 并让func返回修改后的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM