Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

assign instance field to local variable

Tags:

java

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;
}
like image 553
joohwan Avatar asked Jun 22 '16 02:06

joohwan


People also ask

How do I assign an instance variable?

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.

Is instance variable same as field?

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.

What is an instance data field?

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.


2 Answers

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)

like image 78
Michael Markidis Avatar answered Oct 12 '22 08:10

Michael Markidis


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.

like image 40
clstrfsck Avatar answered Oct 12 '22 07:10

clstrfsck