So I am doing a sort here and implementing the Comparator interface using an inner class, exceptionMessage and didJsonParsingFailed are variables declared outside the inner class, now java doesn't allow accessing of local variables using inner class, so this gives me an error, but when I make these two variables as atomic, "AtomicReference" and "AtomicBoolean", in that case program runs fine, I was not able to understand the reason behind it. How does making it Atomic helps? Does java allows access of AtomicVariables in inner class.
P.S- I have to modify these variables in my catch block so I cannot make it final
Collections.sort(list, new Comparator() {
private static final String KEY_NAME = "createdDateTime";
@Override public int compare(Object o1, Object o2) {
String str1;
String str2;
Date d1 = new Date();
Date d2 = new Date();
try {
str1 = (String) ((JSONObject) o1).get(KEY_NAME);
str2 = (String) ((JSONObject) o2).get(KEY_NAME);
d1 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss").parse(str1);
d2 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss").parse(str2);
} catch (JSONException | ParseException e) {
exceptionMessage = "xyz";
didJsonParsingFailed = true;
}
return d1.compareTo(d2);
}
});
CodePudding user response:
How does making it Atomic helps? Does java allows access of AtomicVariables in inner class.
The problem is that you're trying to assign variables inside an anonymous class (i.e. variable = value
).
You're not allowed to do that because of how anonymous classes actually work: when you write an anonymous class, the variables from the outer scope are actually fields inside the anonymous class, that is, the variable in the outer scope and the variable in the anonymous class are actually different; you're not allowed to reassign either, in order to stop them getting out of sync.
On the other hand, with an Atomic*
, you're not reassigning the variable, you're reassigning the value it holds. This is fine, because any variables inside and outside the anonymous class still point to the same Atomic*
object; and, since it's the same object, both places can access its value.
Catching the an exception when sorting doesn't seem like a particularly good idea in the first place. It will lead to inconsistent sorting, violation of general contract etc; and not an obviously-usefully-ordered list.
If you really insist, catch the exception outside the comparison outside the sort
call:
try {
Collections.sort(list, new Comparator<JSONObject>() { ... });
} catch (JSONException | ParseException e) {
exceptionMessage = "xyz";
didJsonParsingFailed = true;
}
Assuming you really don't need to catch inside the Comparator, it would be more easily written as:
Comparator.comparing(j -> new SimpleDateFormat(/* the date format */).parse(j.get(KEY_NAME)))
CodePudding user response:
I was not able to understand the reason behind it.
It's reason is that Variable exceptionMessage
and didJsonParsingFailed
are accessed from within inner class, needs to be final or effectively final.
Refer this answer to understand final and effective final!
How does making it Atomic helps?
Simple, When you make it atomic then you are modifying the content in the atomic variable and not changing/assigning a new reference to that! Same will work with a pojo class as well where you wrap your variables inside a simple pojo class like OuterClassVariables
, instantiate it and use it's setters to set the values from inside the inner class or lambda body.