如何通过引用正确传递 Integer 类?
我希望有人能为我澄清这里发生的事情。我在整数类中进行了一些研究,但由于整数覆盖 +
运算符,我无法弄清楚出了什么问题。我的问题在于这一行:
Integer i = 0;
i = i + 1; // ← I think that this is somehow creating a new object!
这是我的推理: 我知道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);
}
}
}
这是我的预期输出:
Inc: 1 main: 1 Inc: 2 main: 2 Inc: 3 main: 3 Inc: 4 main: 4 Inc: 5 main: 5 Inc: 6 main: 6 ...
这是实际输出。
Inc: 1 main: 0 Inc: 1 main: 0 Inc: 1 main: 0 ...
为什么它会这样?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
有两个问题:
Integer#set(i)
这样的方法。否则你可以利用它。要使其正常工作,您需要重新分配
inc()
方法的返回值。要了解有关按值传递的更多信息,请参阅另一个示例:
There are two problems:
Integer#set(i)
. You could otherwise just make use of it.To get it to work, you need to reassign the return value of the
inc()
method.To learn a bit more about passing by value, here's another example:
上面的好答案解释了OP的实际问题。
如果有人需要传递需要全局更新的数字,请使用 AtomicInteger(),而不是创建建议的各种包装器类或依赖第 3 方库。
AtomicInteger(
) 当然主要用于线程安全访问,但如果性能影响不成问题,为什么不使用这个内置类。额外的好处当然是明显的线程安全性。Good answers above explaining the actual question from the 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.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.整数是不可变的。您可以将 int 包装在自定义包装类中。
The Integer is immutable. You can wrap int in your custom wrapper class.
有两种方法可以通过引用传递
这是执行此操作的示例代码:
输出:
There are 2 ways to pass by reference
Here's a sample code to do it:
Output:
您在这里看到的不是重载的
+
运算符,而是自动装箱行为。Integer
类是不可变的,并且您的代码:被编译器(自动装箱后)视为:
因此您的结论是正确的,即
Integer
实例已更改,但是不是偷偷摸摸的 - 它与 Java 语言的定义一致:-)What you are seeing here is not an overloaded
+
oparator, but autoboxing behaviour. TheInteger
class is immutable and your code:is seen by the compiler (after the autoboxing) as:
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 中,您会在上面的行中收到错误)。当您编写
i + 1
时,编译器首先将 Integer 转换为(原始)int
以执行加法:自动拆箱。接下来,执行i =
编译器将int
转换为(新)整数:自动装箱。所以
+
实际上被应用于原始的int
。You are correct here:
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, doingi = <some int>
the compiler converts fromint
to an (new) Integer: autoboxing.So
+
is actually being applied to primitiveint
s.我认为是自动装箱让你失望了。
这部分代码:
实际上可以归结为如下所示的代码:
当然......不会更改传入的引用。
您可以用这样的方法修复它
I think it is the autoboxing that is throwing you off.
This part of your code:
Really boils down to code that looks like:
Which of course.. will not changes the reference passed in.
You could fix it with something like this
如果您将 inc() 函数更改为此
,您将看到它总是打印“false”。
这意味着加法创建了一个新的 Integer 实例并将其存储在本地变量 i 中(“本地”,因为 i 实际上是所传递的引用的副本),留下了变量调用方法不变。
Integer 是一个不可变的类,这意味着您不能更改它的值,但必须获取一个新实例。在这种情况下,您不必像这样手动执行此操作:
相反,它是通过自动装箱完成的。
If you change your inc() function to this
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 local variable i ("local", because i is actually a copy of the reference that was passed), leaving the variable of the calling method untouched.
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:
instead, it is done by autoboxing.
1 ) 仅引用的副本作为值发送到形式参数。当形参变量被赋予其他值时,对于该整型对象,形参的引用发生变化,但实参的引用保持不变。
公共类 UnderstandingObjects {
}
类 IntObj {
整数a;
}
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.
public class UnderstandingObjects {
}
class IntObj {
Integer a;
}
我们可以使用 Apache Commons Mutable Int
这会产生输出:
We can do this using Apache Commons Mutable Int
This produces output:
对于这个问题,已经有很多答案了。
大多数人都建议包装类..但我们确实不需要创建一个新类。有一种方法没有人提供。
并对问题进行了讨论。但在提供我的解决方案之前我会先简要介绍一下。
我的解决方案比使用包装类更简单。我们可以只使用大小为 1 的数组。
输出
A lot of answers have been given to this problem.
Most people have suggested wrapper classes.. but we really do not need to create a new class. There is one method which no one has provided.
And problem has been discussed. But I will brief before providing my solution.
My solution is simpler than using wrapper class. We can just use array of size 1.
output