I'm trying to avoid a NullPointerException in some code that tries to compare with a string from a HashMap.
The HashMap is well defined but there may or may not be a corresponding entry in the HashMap so I believe this may be where my NPE and the associated Android Studio warning may be coming from.
My code is:
if (region_ids !=null && source_region != null && selected_id != null) {
if (source_region.equals("it") && region_ids.containsKey("it") && !selected_id.equals(region_ids.get("it").toString())) {
// Do stuff for mismatched region
}
}
Where region_ids is the HashMap.
Am I doing enough to prevent NullPointerExceptions?
If so, why is Android Studio still giving me the warning in the IDE?
(Note that the Android-Studio tag is included intentionally because of the last part of this question which is AS specific.)
Update
Based on Code-Apprentice's comment and Nosyara's answer I now have the following two variations on the if statement but still get the NPE warning on the toString() method:
if ( region_ids_string != null && spin_region_id != null && source_region != null && selected_id != null && assoc_ids != null) {
if ( region_ids_string.size() > spin_region_id.getSelectedItemPosition()) {
if (source_region.equals("com_mx") && assoc_ids.get("com_mx") != null && assoc_ids.containsKey("com_mx") && !selected_id.equals(assoc_ids.get("com_mx").toString())) {
return true;
} else if ("com_au".equals(source_region) && assoc_ids.containsKey("com_au") && assoc_ids.get("com_au") != null && !assoc_ids.get("com_au").toString().equals(selected_id)) {
return true;
} else {
return false;
}
} else {
return false;
}
} else {
return false;
}
So I believe I am now checking for null, "", and whether the Key exists in the HashMap but AS still believes it is possible for the statements to generate an NPE...
If you reverse condition with constant to the left, you'll automatically check it for NULLs. Like so:
if ("it".equals(source_region) &&
region_ids.containsKey("it") &&
!(region_ids.get("it").toString().equals(selected_id))) {
// Do stuff for mismatched region
}
Related
I am facing an issue that confused me always while checking the source code in JDK.
Below is code snippet from ConcurrentHashMap.
Why don't to use table varible directly? but rather to assign it to the t local var. is this a recommended style in java?
public boolean containsValue(Object value) {
if (value == null)
throw new NullPointerException();
Node<K,V>[] t;
if ((**t** = **table**) != null) {
Traverser<K,V> it = new Traverser<K,V>(**t**, **t**.length, 0, t.length);
for (Node<K,V> p; (p = it.advance()) != null; ) {
V v;
if ((v = p.val) == value || (v != null && value.equals(v)))
return true;
}
}
return false;
}
If you're running multiple threads then table might be changed by another thread and become null partway through the method. But t cannot be changed elsewhere, because it only exists inside this method. This is a way of avoiding a possible exception.
I have the below utility method and I am using multiple if statements and getting cognitive complexity issue. I went through some links, but I am not able to understand how should I change my code without affecting users of this method.
public static boolean isWrapperValid(WrapperClass wrapper, boolean isTechnicalToken){
String key=null;
boolean isValidWrapper = false;
if (wrapper != null && wrapper.length() > 7
&& wrapper.substring(0, 6).equalsIgnoreCase("XYZ"))
{
wrapper= wrapper.substring(7, wrapper.lastIndexOf('.')+1);
}
if(wrapper != null && wrapper.equalsIgnoreCase("TFR")) {
isValidWrapper=Boolean.TRUE;
}
try {
key = wrapper.getKey();
}
catch (Exception exception) {
return isValidWrapper;
}
if(key!=null) {
Date tokenExpiryTime = key.getExpiresAt();
if(tokenExpiryTime!=null) {
return isValidWrapper;
}
String algorithm=key.getAlgorithm();
if(!DESIRED_ALGO.equals(algorithm)) {
return isValidWrapper;
}
String value6=key.getType();
if(!DESIRED_TYPE.equals(value6)) {
return isValidWrapper;
}
if(key.getValue1()!=null && key.getValue2().size()>0 && key.getValue3()!=null && key.getValue4()!=null && key.getValue5()!=null) {
isValidWrapper=Boolean.TRUE;
}
}
return isValidWrapper;
}
Please share your suggestions to refactor this code.
I don't think that merging many if conditions to one or simply do a code clean up, for example by changing the order of some instructions, can solve your problem.
Your code does not match the single responsibility principle. You should refactor this big method to smaller parts. Due to this it will testable, easier to maintain and read. I spent some time and did this:
public static boolean isWrapperValid(WrapperClass wrapper, boolean isTechnicalToken) {
final WrapperClass unpackedWrapper = unpackWrapper(wrapper);
boolean wrapperValid = isUnpackedWrapperValid(unpackedWrapper);
Key key = null;
try {
key = unpackedWrapper.getKey();
} catch (final Exception exception) {
return wrapperValid;
}
if (key != null) {
if (doesKeyMeetsBasicConditions(key)) {
return wrapperValid;
}
if (doesKeyMeetsValueConditions(key)) {
return true;
}
}
return wrapperValid;
}
protected static WrapperClass unpackWrapper(final WrapperClass wrapper) {
if (wrapper != null && wrapper.length() > 7 && wrapper.substring(0, 6).equalsIgnoreCase("XYZ")) {
return wrapper.substring(7, wrapper.lastIndexOf('.') + 1);
}
return wrapper;
}
protected static boolean isUnpackedWrapperValid(final WrapperClass wrapper) {
return wrapper != null && wrapper.equalsIgnoreCase("TFR");
}
protected static boolean doesKeyMeetsBasicConditions(final Key key) {
Date tokenExpiryTime = key.getExpiresAt();
if (tokenExpiryTime != null) {
return true;
}
String algorithm = key.getAlgorithm();
if (!DESIRED_ALGO.equals(algorithm)) {
return true;
}
String value6 = key.getType();
return !DESIRED_TYPE.equals(value6);
}
protected static boolean doesKeyMeetsValueConditions(final Key key) {
return key.getValue1() != null && key.getValue2().size() > 0
&& key.getValue3() != null && key.getValue4() != null
&& key.getValue5() != null;
}
I don't know the domain logic, so some of my methods have stupid names etc. As you can see, now you have a lot of smaller methods with not many branches (if conditions) - easier to test (a static code is not nice, but you can mock it by using for example PowerMock).
A bit of rewriting delivered a simplification, that still could be improved upon.
public static boolean isWrapperValid(WrapperClass wrapper, boolean isTechnicalToken){
if (wrapper != null && wrapper.length() > 7
&& wrapper.substring(0, 6).equalsIgnoreCase("XYZ"))
{
wrapper = wrapper.substring(7, wrapper.lastIndexOf('.')+1);
}
boolean isValidWrapper = wrapper != null && wrapper.equalsIgnoreCase("TFR");
try {
String key = wrapper.getKey();
if (key != null && key.getExpiresAt() == null
&& DESIRED_ALGO.equals(key.getAlgorithm())
&& DESIRED_TYPE.equals(key.getType())
&& key.getValue1() != null && !key.getValue2().isEmpty()
&& key.getValue3() != null && key.getValue4() != null
&& key.getValue5() != null) {
isValidWrapper = true;
}
}
catch (Exception exception) {
// DO NOTHING
}
return isValidWrapper;
}
After comment: here I catch any exception for all calls.
First of all, Sonar should give you more flags: reusing the wrapper parameter is usually a bad practice, NPE where invoking wrapper.getKey because wrapper can be null, but anyway, not the point...
Try reducing the number of if statements by creating local boolean variables (or possibly 1 big if statement if you have less than 5 or 6 tests, but often less readable). Once it's done, you should only have 1 block testing these boolean variables, and have one return statement, like the example above (not necessarily accurate!):
boolean expired = tokenExpiryTime != null;
boolean desiredAlgo = DESIRED_ALGO.equals(key.getAlgorithm());
boolean desiredType = DESIRED_TYPE.equals(value6);
if (expired || !desiredAlgo || !desiredType) {
return isValidWrapper;
}
However, your Cognitive complexity level seems pretty low if this kind of algorithm triggers it...
Another big way to reduce an algorithm complexity is to turn sub-blocks of code (loops, if and try-catch) into private methods. In your example, it could be something like a checkWrapperValidity method, responsible for every test returning isValidWrapper
I have a little problem with this snippet of code:
#Override
public int compareTo(EventResponse o) {
int compare1 = startTime.compareTo(o.startTime);
if (compare1 == 0 && o.myProviderId != null && o.providerId != null) {
return o.providerId.compareTo(o.myProviderId) != 0 ? -1 : 0;
} else {
return compare1;
}
}
I have EventResponse class which i have created that implements Comparable interface, o.myProviderId is ID of currently signed in user (into application) and o.providerId is ID of user that is assigned to particular object (EventResponse).
What I need to achieve is if there are two objects with the same startTime to show objects assigned to me first and then objects assigned to some other provider/s.
This code snippet should (and I think it did in the past) do the trick but I get error message stating: "Comparison method violates its general contract".
Please help!
The violation of the contract often means that the comparator is not providing the correct or consistent value when comparing objects.
For example :
if (compare1 == 0 && o.myProviderId != null && o.providerId != null) {
return o.providerId.compareTo(o.myProviderId) != 0 ? -1 : 0;
}
So, what happens when o.providerId.compareTo(o.myProviderId) gives you 1 or -1. In both scenario you are going to return -1 isn't it ?
Instead, why not simply return what gets return from compareTo ?
if (compare1 == 0 && o.myProviderId != null && o.providerId != null) {
return o.providerId.compareTo(o.myProviderId);
}
I'm looking to populate an object with some values from a complex xml object. To get to the right value i have to get through a big chain of elements and i have to check them all to not be null. So my code will look like this X 9 times. I don't want to stop the populate process just because one element is missing, I want to 'skip' the null pointer somehow and get to the next propriety. My only idea is to put every line in a try/catch block. Got any better ideas? Thanks
objModel.setProviderHeadquarterName(obj.getObject("YYY") != null && obj.getObject("YYY").getArray("gob") != null && obj.getObject("YYY").getArray("gob").size() > 0 && obj.getObject("YYY").getArray("gob") != null ? obj.getObject("YYY").getArray("gob").getObject(0).getString("gobValue") : "");
objModel.setProviderHeadquarterName(obj.getObject("XXX") != null && obj.getObject("XXX").getArray("tem") != null && obj.getObject("XXX").getArray("tem").size() > 0 && obj.getObject("XXX").getArray("tem") != null ? obj.getObject("XXX").getArray("tem").getObject(0).getString("temValue") : "");
objModel.setProviderHeadquarterName(obj.getObject("ZZZ") != null && obj.getObject("ZZZ").getArray("has") != null && obj.getObject("ZZZ").getArray("has").size() > 0 && obj.getObject("ZZZ").getArray("has") != null ? obj.getObject("ZZZ").getArray("has").getObject(0).getString("hasValue") : "");
How can
You can wrap this in an Optional and deal with the nulls implicitly:
Optional.of(obj).map(o -> o.getObject("YYY")).map(o -> o.getArray("gob")) /* [snip] */
.orElse(""); //etc
To answer your question literally, you could extract that in a separate method and catch the potential exceptions. But that's not best practice:
private static Object getValueOrNull(Supplier<Object> s) {
try {
return s.get();
} catch (Exception e) { //narrow down the exception if possible
return null;
}
}
Which you can call like this (the value may be null):
Object value = getValueOrNull(() -> obj.getObject("YYY").getArray("gob").getObject(0).getString("gobValue"));
So today my data structures final had an exam question that asked this:
"Consider the BinaryTree class and add two recursive methods (independent from each other) named compBT to compare two binary trees. If the two binary trees are structurally identical (i.e., they look the same when the objects stored in the nodes are ignored), each of the two methods returns true; otherwise, each returns false. The first method should be an instance method and the second method should be a class method. Do not access the underlying data structure directly. Note: each method should not take more than 6 lines and be properly indented."
I was able to produce this for the class method:
public static boolean compareTrees(BinaryTree t1, BinaryTree t2) {
if (t1 == null && t2 == null) return true;
if ((t1 == null && t2 != null) || (t1 != null && t2 == null)) return false;
return compareTrees(t1.left, t2.left) && compareTrees(t1.right, t2.right);
}
I felt pretty confident about this answer, but writing the instance method had me totally stumped, especially since it had to be independent from the class method. All I was able to produce was the following:
public boolean compareTrees(BinaryTree t) {
if (t == null) return false;
return (compareTrees(this.left) && (t.left)) && (compareTrees(this.right) && compareTrees(t.right));
}
I know the method is incorrect since it will always return false because there is only one base case which will always be met. My thought process behind that particular base case is that if the parameter is null, then return false since there is a structural inequality because the caller cannot be null (only non-null references can call instance methods). But I didn't know what else to do from there.
Can anyone chime in? I thought this problem was pretty interesting.
Edit: adding in BinaryTree class.
Here's what the BinaryTree class looked like:
class BinaryTree {
public int value;
public BinaryTree left;
public BinaryTree right;
public BinaryTree(int x) { value = x;}
}
For instance method, all that changes is that check is before recursion, no in it:
public boolean compareTrees(BinaryTree other) {
if (left == null) != (other.left == null) return false;
if (right == null) != (other.right == null) return false;
if (left != null && !left.compareTrees(other.left)) return false;
if (right != null && !right.compareTrees(other.right)) return false;
return true;
}
I think you've recognized the basic problem. In your static method, you can pass null for both child trees when you call the method recursively. But in your instance method, you can only do that for the parameter. You can't do that for the instance method, since you can't call an instance method on null.
Well, if you can't call the instance method recursively on a null child, you have to handle the null child case before the recursive call. That's the key here, the realization that you will have to rearrange your logic. So your logic will need to be something like this:
If the parameter is null, return false (like you already did)
If the instance's left child is null, then:
2.1 If the parameter's left child is not null, return false
2.2 If the parameter's left child is null, keep going with step 4
If the instance's left child is not null, then call recursively on the left child (it doesn't matter if the parameter's left child is null, because that will be caught be #1), and return false if the recursive call returns false
4-5. Same steps for the right child
If we've gotten this far, and no check has failed, then we can return true
So the code looks something like this:
public boolean compareTrees(BinaryTree t) {
if (t == null) return false;
if (this.left == null) {
if (t.left != null) {
return false;
}
}
else if (!this.left.compareTrees(t.left)) {
return false;
}
if (this.right == null) {
if (t.right != null) {
return false;
}
}
else if (!this.right.compareTrees(t.right)) {
return false;
}
return true;
}
EDIT: I just now noticed the requirement that the method not be more than 6 lines. So I guess my answer won't work. On the other hand, I could make it work by compressing a bunch of stuff onto a few lines.
public boolean compareTrees(BinaryTree t) {
if (t == null) return false;
if (this.left == null && t.left != null) return false;
if (this.left != null && !this.left.compareTrees(t.left)) return false;
if (this.right == null && t.right != null) return false;
if (this.right != null && !this.right.compareTrees(t.right)) return false;
return true;
}
I could make it even shorter by combining the last two lines into one. But
if your professor is going to reward compressed, harder-to-read code such as this, and fail cleaner code like I had in my earlier example, shame on him.
More: OK, if your professor measures code quality by a smaller number of lines, this should make him ecstatic, even though all my colleagues would blast it in a code review:
public boolean compareTrees(BinaryTree t) {
return !((t == null) || (this.left == null && t.left != null) || (this.left != null && !this.left.compareTrees(t.left)) || (this.right == null && t.right != null) || (this.right != null && !this.right.compareTrees(t.right)) );
}