Pardon me if this is a stupid question.. I was wondering if there is any support for following comparison in Java:
(a, b, c .... != null) in place for :
(a != null && b != null && c != null && d ! null and so on ..)
I was trying to make code more readable as my code which is almost unreadable due to multiple condition in single statement.
code :
variable = (rest.host != null && rest.payload != null
&& rest.lockQueue != null && rest.endpoint != null ) || rest.default.setState
|| rest.scheduler.locked && rest.scheduler.queue.isFull()
&& lastPayload.getActivity.status.executing ? onExecute(rest.payload) : wait(TIME);
If your elements are in a collection, use collection.stream().allMatch(x -> x != null). Actually, there's even a predicate for that: collection.stream().allMatch(Objects::nonNull).
If your elements aren't in a collection, you can still use Arrays.asList() to create an ad-hoc list from them. So, in your case:
Arrays.asList(rest.host, rest.payload, rest.lockQueue, rest.endpoint).stream().allMatch(Objects::nonNull)
EDIT: actually, as someone mentioned in another answer, there is a method that creates a stream directly, namely Stream.of(...). So:
Stream.of(rest.host, rest.payload, rest.lockQueue, rest.endpoint).allMatch(Objects::nonNull)
You could do something like this to make sure everything is not null, if using a Java version lower than 8. Otherwise I would go with the other people's answers using streams.
private boolean checkIfNotNull( Object ... objects ) {
for(int i = 0; i < objects.length; i++) {
if(objects[i] == null)
return false;
}
return true;
}
and you could pass in all the objects that you want to check if they are null.
then you can call this in the if statement such as
if( checkIfNotNull( a, b, c, d, e, f, g ) ) {
//do stuff
}
In java 8, it could be done as next Stream.of(a, b, c, d).allMatch(Objects::nonNull), it will return true if they are all non null.
I think if you want your code more readable, you should replace your comparisons with method calls that "says" what each comparison is.
Example:
if (isAllRight(a, b, c)) {
...
}
In other cases you can break them into single comparisons and check one by one:
if (a == NUL) {
return false;
}
if (b == NULL) {
return false;
}
return true;
Related
I currently have an enumlist. The enumlist gets filled at random, so there is a possibility that one has the value null. That is logical because it doesn't get filled.
The problem is further in my code I have:
if (player.Enumlist().get(CART_BLACK) > 0) {
}
Java throws a NullPointerException. Is there something I could add to the if-statement to prevent this error?
If get(CART_BLACK) may return null:
Get the value before the condition and replace it with a negative value if it's null:
Integer cartBlack = player.Enumlist().get(CART_BLACK);
if (cartBlack == null) cartBlack = -1;
if (cartBlack > 0) {
If player.Enumlist() may return null
Similar, but not quite identical:
final Enumlist list = player.Enumlist();
final int cartBlack = list == null ? -1 : list.get(CART_BLACK);
if (cartBlack > 0) {
You'll need to guard against nullity:
if(player.Enumlist().get(CART_BLACK) != null &&
player.Enumlist().get(CART_BLACK) > 0) {...}
or a more efficient version:
Integer temp = player.Enumlist().get(CART_BLACK);
if (temp != null && temp > 0){...}
if( player.Enumlist().get(CART_BLACK) != null && player.Enumlist().get(CART_BLACK) > 0) {
}
This will work because ifs are checked from left to right, and if one condition fails the rest won't be evaluated and you won't get the NPE.
Correcting the issue at the end makes the trick but it is not fine because it means that it may occur in other invocations. Besides, as a consequence, you may finish by overusing not null guards as you will never know if the null is a normal case.
So you should favor the use of Optional (Java 8 or Guava) as return rather than null to make your API clearer (it may return an empty thing so convey that) and more robust (the contained object has to be specifically unwrapped).
For example :
Optional<Integer> optValue = player.Enumlist().get(CART_BLACK);
optValue.filter(v -> v > 0)
.ifPresent( v -> ...);
You need to do Null Checking:
if (player == null || player.Enumlist () == null) {
throw new Exception("Player or Enumlist cannot be null");
}
You should also check that the Integer value is not null, but I guess that would be pretty weird if you wrote the code.
You are using get which could give you an IndexOutOfBoundsException eventually. You could check that using the size method or using streams.
If (player.Enumlist().size() > CART_BLACK && player.Enumlist().get(CART_BLACK) != null && player.Enumlist().get(CART_BLACK) > 0) {
//...
}
You may check for Null also handle the exception using try..catch block
try
{
if( player.Enumlist().get(CART_BLACK)!=null && player.Enumlist().get(CART_BLACK) > 0)
{
}
}
catch(NullPointerException)
{
//handle exception here
}
I am using Sonar and its giving me the suggestion "Expressions should not be too complex"
How can I make a better representation of below code?
Code
if (eDelivery != null && Boolean.parseBoolean(eDelivery.getReceiveConfirmationElectronically()) &&
!Boolean.parseBoolean(eDelivery.getInvalidEmailAddress()) && !Boolean.parseBoolean(eDelivery.getEmailUndeliverable()) &&
eDelivery.getUserEmailAddress() != null && !eDelivery.getUserEmailAddress().isEmpty()) {
// Implementation code
}
These conditions all relate to the eDelivery object, so deal with this there.
First, there's the question of why you're doing all these parseBoolean calls for properties that look like they should be boolean to start with. But okay, let's assume that you can't change that. Fine, so add 2ndary methods:
public class EDelivery {
public boolean isReceiveConfirmationElectronically() {
return Boolean.parseBoolean(getReceiveConfirmationElectronically())
}
// &etc...
Already that cleans it up considerably:
if (eDelivery != null && eDelivery.isReceiveConfirmationElectronically() &&
!eDelivery.isInvalidEmailAddress() && !eDelivery.isEmailUndeliverable() &&
eDelivery.getUserEmailAddress() != null && !eDelivery.getUserEmailAddress().isEmpty()) {
// Implementation code
But that doesn't address the number of conditions. So now:
// in EDelivery class
public boolean isEmailGood() {
return !isInvalidEmailAddress() && !isEmailUndeliverable() &&
getUserEmailAddress() != null && !getUserEmailAddress().isEmpty())
}
So now we're at:
if (eDelivery != null && eDelivery.isReceiveConfirmationElectronically() &&
eDelivery.isEmailGood()) {
// Implementation code
At this point you've met the requirement, but if you wanted to take it a little further:
// in EDelivery class
public boolean canSendElectronicConfirmation(){
return isEmailGood() && isReceiveConfirmationElectronically();
}
Which reduces your original if statement to
if (eDelivery != null && eDelivery.canSendElectronicConfirmation()) {
// Implementation code
I'm trying to figure out the best way of grabbing the smallest of two numbers when the numbers are attributes inside of two different objects. Each, but not both, of the objects can be null, which can lead to null pointer exceptions. Each object has their own getValue() method, which will return a Long value. There's the basic if/else that I'd prefer not to do:
if (obj1 != null && obj2 != null) { // neither object is null
minValue = obj1.getValue() <= obj2.getValue() ? obj1.getValue() : obj2.getValue();
} else if (obj1 == null && obj2 != null) { // only obj1 is null
minValue = obj2.getValue();
} else { // only obj2 is null (they can't both be null, so we don't need an if for the situation where they're both null)
minValue = obj1.getValue();
}
I've tried some other things:
// can throw null pointer exception
Collections.min(Arrays.asList(obj1.getValue(), obj2.getValue()));
// while both objects have a getValue() method, they are of different types, so mapping doesn't work
Collections.min(Arrays.asList(obj1, obj2)
.filter(obj -> obj != null)
.map(obj -> obj.getValue()) // this line will fail since the methods correspond to different objects
.collect(Collectors.toList()));
I feel like this should be a fairly easy problem, but my brain's not allowing it to work. There's due to be some min function where you can bipass a situation where the object can be null?
long minValue = Math.min(obj1 == null ? Long.MAX_VALUE : obj1.getValue(),
obj2 == null ? Long.MAX_VALUE : obj2.getValue());
I am not sure I fully understand your question, but if I do, something like this could work:
if(obj1 == null)
minValue = obj2.getValue();
else if(obj2 == null)
minValue = obj1.getValue();
else minValue = obj1.getValue() < obj2.getValue() ? obj1.getValue() : obj2.getValue();
You could have a method that takes in your ObjType, does a null check and returns Long.MAX_VALUE, or the value if it's null.
public Long getVal(ObjType val)
{
if(val != null)
{
return val.getValue();
}
return Long.MAX_VALUE;
}
then do
Math.min(obj1, obj2);
I have compareObjects method implemented as below
public static int compareObjects(Comparable a, Comparable b){
if (a == null && b == null){
return 0;
} else if (a == null && b != null){
return -1;
} else if (a != null && b == null){
return 1;
} else {
return a.compareTo(b);
}
}
When I run this through findBugs, I get this suggestion on the line return a.compareTo(b):
There is a branch of statement that, if executed, guarantees that a null value will be dereferenced, which would generate a NullPointerException when the code is executed. Of course, the problem might be that the branch or statement is infeasible and that the null pointer exception can't ever be executed; deciding that is beyond the ability of FindBugs. Due to the fact that this value had been previously tested for nullness, this is a definite possibility.
At this point a can never be null. Why does FindBugs show me this suggestion? How can I correct this; what is the correct way to implement compareObjects()?
I think it might be because you don't need the extra && statements. After the first if statement you already know that one of them is null.
public static int compareObjects(Comparable a, Comparable b){
if (a == null && b == null){
return 0;
} else if (a == null){
return -1;
} else if (b == null){
return 1;
} else {
return a.compareTo(b);
}
}
Looking at it again , try this code:
if (a == null && b == null){
return 0;
}
if (a == null){
return -1;
}
if (b == null){
return 1;
}
return a.compareTo(b);
It may be a limitation in FindBugs; I agree that you've covered all the bases, but your null-check is split across two different conditions. Now these conditions happen to be complementary, so at least one of them will fire if a is null, but depending how sophisticated FindBugs is, it may not recognise this.
Two options here, then:
Just ignore the FindBugs warning. Due to its nature it will raise some false positives from time to time, so don't feel like you have to rewrite your code to make it 100% happy if you don't think the rewrite is worthwhile on its own merits.
You can use the #SuppressWarnings annotation to actually communicate this to FindBugs, if you want the report to show a nice big zero at the end. See this question for an example.
Restructure the condition so that the nullity check on a is more explicit, by nesting if blocks:
if (a == null) {
return b == null ? 0 : -1;
}
return b == null ? 1 : a.compareTo(b);
Depending on your tastes and style that might be a better rewrite anyway, in that is more clearly says "if a is null, do this calculation and return it, otherwise do this calculation". You can of course change the ternary condition into another if-else block if you prefer that.
How do I implement this equality comparison is a sane java way?
boolean x = (a == b) || (a.equals(b))
I want to make sure the content of both objects is equal but null is also ok, i.e. both can be null and are thus equal.
Update: just to be clear, I have to implement this comparison several times and don't want to copy&paste this stuff every time, especially with lenghty object names. With 'a' and 'b' it looks small and simple, but tends to grow... I'd like to know if I'm missing some existing Java feature for this.
You might want to have a look at the always useful Apache Commons Lang, more precisely ObjectUtils.equals().
Another way to do
boolean x = null==a ? null==b : a.equals(b);
The typical pattern is:
if (a == b)
{
return true;
}
if (a == null || b == null)
{
return false;
}
// Now deal with a and b, knowing that they are non-identical, non-null references
Yes, it's wordy - but if you separate it out into its own method, you can keep it under reasonable control.
What happens if a is null but b is not? I think you really want:
boolean x = (a == null && b == null) || (a != null && a.equals(b))
EDIT: You could implement a static NullEquals method for the class that takes two objects of that class and does the comparison as above to avoid rewriting and make the code a little cleaner.
public class MyClass {
public static boolean NullEquals( MyClass a, MyClass b )
{
return (a == null && b == null) || (a != null && a.equals(b));
}
}
if (MyClass.NullEquals(a,b))
{
...
}
Not a direct answer, but if you have lot of objects that can be or not null, may be that indicates some problem with your code. Take a look at the Null Pattern , that is an alternative way to represent the absence of an object
What about:
boolean x = equals( a, b );
public static boolean equals( Object a, Object b ) {
if ( a == null && a == b ) {
return true;
} else {
return a == b || a.equals( b );
}
}
Let me see.
if a is null and a is b then it's ok
if a is not null then if a == b ( same ref ) return true by shortcircuit
if a is not b ( 2dns part of the OR probably b is null ) then return a ( not null ) .equals( b ) whatever b is
Yeap covered.
Can not add comment,
Treat this as comment to Jon Skeet's answer.
Does Null = Null true or false in Java.
More specifically what should be Null = Null should be treated and How and why the different language treat this case ?
The most common way of doing it is:
a==null ? b==null : a.equals(b)
A potentially slightly more efficient, but less clear, expressions is:
a==b || (a!=null && a.equals(b))
You can of course put this inside a method:
public static boolean eq(Object a, Object b) {
return a==b || (a!=null && a.equals(b));
}
Note the original question code NPEs if a is null and b is non-null.
For performance reasons, usually it is good to check for identity before executing any other logic, as was done in the question. However, many of the answers don't take this into account.
The best place to put the identity check is in the implementation of the equals method on your class:
public boolean equals(Object obj) {
if(this == obj) return true;
...
}
If this has/can be done, you can do the comparison easily:
a == null ? b == null : a.equals(b);
Otherwise you might have to check for identity yourself:
a == null ? b == null : (a == b || a.equals(b));