Java 如何通过引用正确传递 Integer 类?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3330864/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I pass an Integer class correctly by reference?
提问by sixtyfootersdude
I am hoping that someone can clarify what is happening here for me. I dug around in the integer class for a bit but because integer is overridingthe +
operator I could not figure out what was going wrong. My problem is with this line:
我希望有人能为我澄清这里发生的事情。我在 integer 类中挖掘了一些,但因为 integer覆盖了+
运算符,我无法弄清楚出了什么问题。我的问题是这一行:
Integer i = 0;
i = i + 1; // ← I think that this is somehow creating a new object!
Here is my reasoning: I know that java is pass by value (or pass by value of reference), so I think that in the following example the integer object should be incremented each time.
这是我的推理:我知道 java 是按值传递(或按引用值传递),所以我认为在下面的示例中,整数对象每次都应该递增。
public class PassByReference {
public static Integer inc(Integer i) {
i = i+1; // I think that this must be **sneakally** creating a new integer...
System.out.println("Inc: "+i);
return i;
}
public static void main(String[] args) {
Integer integer = new Integer(0);
for (int i =0; i<10; i++){
inc(integer);
System.out.println("main: "+integer);
}
}
}
This is my expected output:
这是我的预期输出:
Inc: 1 main: 1 Inc: 2 main: 2 Inc: 3 main: 3 Inc: 4 main: 4 Inc: 5 main: 5 Inc: 6 main: 6 ...
This is the actual output.
这是实际输出。
Inc: 1 main: 0 Inc: 1 main: 0 Inc: 1 main: 0 ...
Why is it behaving like this?
为什么会这样?
采纳答案by BalusC
There are two problems:
有两个问题:
- Integer is pass by value, not by reference. Changing the reference inside a method won't be reflected into the passed-in reference in the calling method.
- Integer is immutable. There's no such method like
Integer#set(i)
. You could otherwise just make use of it.
- 整数是按值传递,而不是按引用传递。更改方法内的引用不会反映到调用方法中传入的引用中。
- 整数是不可变的。没有像这样的方法
Integer#set(i)
。否则你可以使用它。
To get it to work, you need to reassign the return value of the inc()
method.
要使其工作,您需要重新分配该inc()
方法的返回值。
integer = inc(integer);
To learn a bit more about passing by value, here's another example:
要了解有关按值传递的更多信息,请参阅另一个示例:
public static void main(String... args) {
String[] strings = new String[] { "foo", "bar" };
changeReference(strings);
System.out.println(Arrays.toString(strings)); // still [foo, bar]
changeValue(strings);
System.out.println(Arrays.toString(strings)); // [foo, foo]
}
public static void changeReference(String[] strings) {
strings = new String[] { "foo", "foo" };
}
public static void changeValue(String[] strings) {
strings[1] = "foo";
}
回答by bwawok
I think it is the autoboxing that is throwing you off.
我认为是自动装箱让你失望了。
This part of your code:
这部分代码:
public static Integer inc(Integer i) {
i = i+1; // I think that this must be **sneakally** creating a new integer...
System.out.println("Inc: "+i);
return i;
}
Really boils down to code that looks like:
真正归结为如下所示的代码:
public static Integer inc(Integer i) {
i = new Integer(i) + new Integer(1);
System.out.println("Inc: "+i);
return i;
}
Which of course.. will not changes the reference passed in.
当然,这不会改变传入的引用。
You could fix it with something like this
你可以用这样的东西来修复它
public static void main(String[] args) {
Integer integer = new Integer(0);
for (int i =0; i<10; i++){
integer = inc(integer);
System.out.println("main: "+integer);
}
}
回答by rsp
What you are seeing here is not an overloaded +
oparator, but autoboxing behaviour. The Integer
class is immutable and your code:
您在这里看到的不是重载的操作+
符,而是自动装箱行为。该Integer
班是不可改变的,你的代码:
Integer i = 0;
i = i + 1;
is seen by the compiler (after the autoboxing) as:
编译器(自动装箱后)将其视为:
Integer i = Integer.valueOf(0);
i = Integer.valueOf(i.intValue() + 1);
so you are correct in your conclusion that the Integer
instance is changed, but not sneakily - it is consistent with the Java language definition :-)
因此,您的结论是正确的,即Integer
实例已更改,但不是偷偷摸摸的 - 它与 Java 语言定义一致:-)
回答by f1sh
If you change your inc() function to this
如果您将 inc() 函数更改为此
public static Integer inc(Integer i) {
Integer iParam = i;
i = i+1; // I think that this must be **sneakally** creating a new integer...
System.out.println(i == iParam);
return i;
}
then you will see that it always prints "false". That means that the addition creates a new instance of Integer and stores it in the localvariable i ("local", because i is actually a copy of the reference that was passed), leaving the variable of the calling method untouched.
然后你会看到它总是打印“false”。这意味着添加会创建一个新的 Integer 实例并将其存储在局部变量 i(“local”,因为 i 实际上是传递的引用的副本)中,而调用方法的变量保持不变。
Integer is an immutable class, meaning that you cannot change it's value but must obtain a new instance. In this case you don't have to do it manually like this:
Integer 是一个不可变的类,这意味着你不能改变它的值,但必须获得一个新的实例。在这种情况下,您不必像这样手动执行此操作:
i = new Integer(i+1); //actually, you would use Integer.valueOf(i.intValue()+1);
instead, it is done by autoboxing.
相反,它是通过自动装箱完成的。
回答by Markos
The Integer is immutable. You can wrap int in your custom wrapper class.
整数是不可变的。您可以将 int 包装在您的自定义包装类中。
class WrapInt{
int value;
}
WrapInt theInt = new WrapInt();
inc(theInt);
System.out.println("main: "+theInt.value);
回答by user85421
You are correct here:
你在这里是正确的:
Integer i = 0;
i = i + 1; // <- I think that this is somehow creating a new object!
First: Integer is immutable.
第一:整数是不可变的。
Second: the Integer class is not overriding the +
operator, there is autounboxing and autoboxing involved at that line (In older versions of Java you would get an error on the above line).
When you write i + 1
the compiler first converts the Integer to an (primitive) int
for performing the addition: autounboxing. Next, doing i = <some int>
the compiler converts from int
to an (new) Integer: autoboxing.
So +
is actually being applied to primitive int
s.
第二:Integer 类没有覆盖+
运算符,该行涉及自动拆箱和自动装箱(在旧版本的 Java 中,您会在上述行中收到错误)。
当您编写i + 1
编译器时,首先将 Integer 转换为(原始)int
以执行加法:自动拆箱。接下来,i = <some int>
编译器将 from 转换int
为(新的)Integer:自动装箱。
所以+
实际上被应用于原始int
s。
回答by Rishi Dua
There are 2 ways to pass by reference
有两种方法可以通过引用传递
- Use org.apache.commons.lang.mutable.MutableIntfrom Apache Commons library.
- Create custom class as shown below
- 使用Apache Commons 库中的org.apache.commons.lang.mutable.MutableInt。
- 创建自定义类,如下所示
Here's a sample code to do it:
这是一个示例代码来做到这一点:
public class Test {
public static void main(String args[]) {
Integer a = new Integer(1);
Integer b = a;
Test.modify(a);
System.out.println(a);
System.out.println(b);
IntegerObj ao = new IntegerObj(1);
IntegerObj bo = ao;
Test.modify(ao);
System.out.println(ao.value);
System.out.println(bo.value);
}
static void modify(Integer x) {
x=7;
}
static void modify(IntegerObj x) {
x.value=7;
}
}
class IntegerObj {
int value;
IntegerObj(int val) {
this.value = val;
}
}
Output:
输出:
1
1
7
7
回答by Hans
Good answers above explaining the actual question from the OP.
上面的好答案解释了 OP 的实际问题。
If anyone needs to pass around a number that needs to be globally updated, use the AtomicInteger(
) instead of creating the various wrapper classes suggested or relying on 3rd party libs.
如果有人需要传递需要全局更新的数字,请使用AtomicInteger(
) 而不是创建建议的各种包装类或依赖 3rd 方库。
The AtomicInteger(
) is of course mostly used for thread safe access but if the performance hit is no issue, why not use this built-in class. The added bonus is of course the obvious thread safety.
的AtomicInteger(
)当然是主要用于线程安全的访问,但如果对性能的影响是没有问题,为什么不利用这个内置类。额外的好处当然是明显的线程安全性。
import java.util.concurrent.atomic.AtomicInteger
回答by awinas kannan
1 ) Only the copy of reference is sent as a value to the formal parameter. When the formal parameter variable is assigned other value ,the formal parameter's reference changes but the actual parameter's reference remain the same incase of this integer object.
1 ) 只有引用的副本作为值发送给形参。当形参变量被赋值为其他值时,形参的引用发生了变化,但实参的引用在这个整数对象的情况下保持不变。
public class UnderstandingObjects {
公共类理解对象{
public static void main(String[] args) {
Integer actualParam = new Integer(10);
changeValue(actualParam);
System.out.println("Output " + actualParam); // o/p =10
IntObj obj = new IntObj();
obj.setVal(20);
changeValue(obj);
System.out.println(obj.a); // o/p =200
}
private static void changeValue(Integer formalParam) {
formalParam = 100;
// Only the copy of reference is set to the formal parameter
// this is something like => Integer formalParam =new Integer(100);
// Here we are changing the reference of formalParam itself not just the
// reference value
}
private static void changeValue(IntObj obj) {
obj.setVal(200);
/*
* obj = new IntObj(); obj.setVal(200);
*/
// Here we are not changing the reference of obj. we are just changing the
// reference obj's value
// we are not doing obj = new IntObj() ; obj.setValue(200); which has happend
// with the Integer
}
}
}
class IntObj { Integer a;
class IntObj { 整数 a;
public void setVal(int a) {
this.a = a;
}
}
}