[英]Difference between Integer, AtomicInteger in java
When I am working with optional class of java like below当我使用 java 的可选 class 时,如下所示
Integer total = null;
Optional<Integer> b = Optional.of(new Integer(10));
b.ifPresent(b -> total =b);
The above code is not working(Error: java: local variables referenced from a lambda expression must be final or effectively final) but, when I use the AtomicInteger, It will work.上面的代码不起作用(错误:java:从 lambda 表达式引用的局部变量必须是最终的或有效的最终)但是,当我使用 AtomicInteger 时,它会起作用。 Why this happens?为什么会发生这种情况?
Optional<Integer> b = Optional.of(new Integer(10));
AtomicInteger total = new AtomicInteger();
b.ifPresent(b -> total.set(b));
You can do it like this:你可以这样做:
Integer total = Optional.of(new Integer(10)).orElse(null);
And if the Optional
value can be nullable then:如果Optional
值可以为空,那么:
Integer total = Optional.ofNullable(new Integer(10)).orElse(null);
Optional.ofNullable
will prevent NPE in case of null
value. Optional.ofNullable
将在null
值的情况下阻止NPE 。
The reason you're getting this error in the first example is that in lambda expression you're not allowed to change the reference of the local variables.在第一个示例中出现此错误的原因是在 lambda 表达式中不允许更改局部变量的引用。 That's why they need to be either declared final
or effectively final.这就是为什么它们需要被宣布为final
的或实际上是最终的。
And the reason the second example is working because here you're not changing the reference of the total
variable.第二个示例之所以有效,是因为在这里您没有更改total
变量的引用。 You're only updating its value using its set()
method.您只是使用它的set()
方法更新它的值。
The AtomicInteger class protects an underlying int value by providing methods that perform atomic operations on the value. AtomicInteger class 通过提供对值执行原子操作的方法来保护底层 int 值。 It shall not be used as a replacement for an Integer class.它不能用作 Integer class 的替代品。
the primary use of AtomicInteger is when we are in multi-threaded context and we need to perform atomic operations on an int value without using synchronized keyword. AtomicInteger 的主要用途是当我们处于多线程上下文中时,我们需要在不使用同步关键字的情况下对 int 值执行原子操作。
Using the AtomicInteger is equally faster and more readable than performing the same using synchronization.使用 AtomicInteger 比使用同步执行同样的操作更快、更易读。
In this case you are not just observing a difference between the two classes, but rather a difference in how you are using them.在这种情况下,您不仅观察到两个类之间的差异,而且还观察到您使用它们的方式的差异。
b.ifPresent(b -> total =b);
This attempts to assign a new reference, a reference to a different Integer
object, to b
.这试图分配一个新的引用,一个对不同Integer
object 的引用,给b
。 This would neither be allowed with Integer
, AtomicInteger
or any other type. Integer
, AtomicInteger
或任何其他类型都不允许这样做。
b.ifPresent(b -> total.set(b));
This calls a method ( set
) in the existing AtomicInteger
object.这将调用现有AtomicInteger
set
中的方法 ( set )。 Calling a method from within a lambda is allowed for both Integer
, AtomicInteger
and all other classes. Integer
、 AtomicInteger
和所有其他类都允许从 lambda 中调用方法。 One important difference for your use case, though, is that Integer
hasn't got a method that allows you to change the value since the class is immutable.但是,您的用例的一个重要区别是Integer
没有一种方法可以让您更改值,因为 class 是不可变的。
What to do instead?该怎么做? See the good answer by Mushif Ali Nawaz .请参阅Mushif Ali Nawaz 的好答案。
PS If you want to know more about the difference between the two classes, see this question: What is the difference between Atomic Integer and Normal immutable Integer class in Java? PS If you want to know more about the difference between the two classes, see this question: What is the difference between Atomic Integer and Normal immutable Integer class in Java?
You asked why the behaviour of Integer
and AtomicInteger
is different in your case.您问为什么Integer
和AtomicInteger
的行为在您的情况下有所不同。 The reason really has nothing to do with AtomicInteger
.原因确实与AtomicInteger
无关。 Rather the difference is that Integer
is immutable and, therefore, the only way of changing the value of a reference to an Integer
is through assignment.相反,不同之处在于Integer
是不可变的,因此,更改对Integer
的引用值的唯一方法是通过赋值。 But lambda expressions do not allow assignment to a local variable that is outside the scope of the expression.但是 lambda 表达式不允许分配给表达式的 scope 之外的局部变量。
There are several ways you could resolve this without using AtomicInteger
:有几种方法可以在不使用AtomicInteger
的情况下解决此问题:
MutableInteger
that can be set inside the lambda创建您自己的MutableInteger
可以在 lambda 中设置Integer
an object variable rather than local variable使Integer
成为 object 变量而不是局部变量orElse
or the various alternatives to return the value rather than setting it inside ifPresent
使用orElse
或各种替代方法来返回值,而不是在ifPresent
中设置它Note also that you might consider OptionalInt
rather than Optional<Integer>
.另请注意,您可能会考虑OptionalInt
而不是Optional<Integer>
。
They behave differently because you are doing two totally things.他们的行为不同,因为您正在做两件事。
In your first:在你的第一个:
b.ifPresent(b -> total =b);
The variable “total” represents an area in memory that you are changing the value of.变量“total”表示 memory 中您正在更改其值的区域。 That is what is not allowed.那是不允许的。
In the second:在第二:
b.ifPresent(b -> total.set(b));
The variable “total” represents an area in memory that is referencing (or pointing to) an instance of the class AtomicInteger.变量“total”表示 memory 中引用(或指向)class AtomicInteger 实例的区域。 You are not changing that variable, but simply calling a method on it.您没有更改该变量,而只是在其上调用方法。 Since “total” itself remains unchanged, it is what is termed “effectively final”, and so is allowed.由于“总”本身保持不变,因此被称为“有效最终”,因此是允许的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.