This is keySet()
method on HashMap
class from JDK. Why did the author assign the field keySet
to local variable ks
?
public Set<K> keySet() {
Set<K> ks;
return (ks = keySet) == null ? (keySet = new KeySet()) : ks;
}
What is the difference between the above and the below? Does this have something to do with thread-safety?
public Set<K> keySet() {
return (keySet == null ? (keySet = new KeySet()) : keySet;
}
Values can be assigned during the declaration or within the constructor. Instance variables can be accessed directly by calling the variable name inside the class. However, within static methods (when instance variables are given accessibility), they should be called using the fully qualified name.
Field, member, member variable, instance variable, (also property in a limited sense), all are the same. They are variables that are declared at class level in a class.
An instance field, in C#, is a variable of any type contained within a class or struct, and is used to store object data. It is a member of its containing type with one copy of the field for each instance of the containing type. Instance fields represent the data of a class that enables an object to maintain its state.
If you look at the keySet
declaration in the abstract class AbstractMap<K,V>
, you will see that it is defined as:
transient volatile Set<K> keySet;
Since it is volatile, reading it just once by using the local variable assignment is cheaper than reading it twice as would be in the other example you provided.
Furthermore, if you were to return the keySet
variable directly, then all the client code would be dealing with a volatile reference vs. a non-volatile reference (i.e. the Set<K> ks
)
To expand slightly on Michael's answer, I expect it is there to ensure that the keySet()
method never returns null
, possibly in addition to providing performance benefits noted.
Given this code:
public Set<K> keySet() {
return (keySet == null ? (keySet = new KeySet()) : keySet;
}
It would be at least theoretically possible in multi-threaded code that the keySet
field could be set to null
between the first read (keySet == null
) and the second read, where it is returned. I haven't looked at the rest of the code, but I assume there are other places where keySet
is potentially assigned null
. Whether this is as a result of an issue seen in the wild, or a defensive measure would be a question for the authors.
The actual code:
public Set<K> keySet() {
Set<K> ks;
return (ks = keySet) == null ? (keySet = new KeySet()) : ks;
}
...doesn't have this problem as the field is only read once.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With