Operator precedence - Arithmetic and Conditional operators - java

I want to understand why the following code throws Null pointer exception.
import java.util.List;
public class Test {
public static void main(String[] args) {
List<String> names = null;
System.out.println("Result is: " + names == null ? null : names.size());
}
}

The issue is that your print statement is evaluated as:
System.out.println(("Result is: " + names) == null ? null : names.size());
This is due to the fact that + has more precedence than ?: operator So, as the string - "Result is null" is not equal to null, evaluating names.size() throws NPE.
Note that, when null is used in string concatenation, it is automatically converted to "null". So, "Result is: " + null will not throw NPE. This is as per JLS - String Conversion:
If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l).
To fix the issue, you should add parenthesis around your conditional expression to enforce greater precendence to it:
System.out.println("Result is: " + (names == null ? null : names.size()));

Correcting Jigar's answer, this actually works:
someString + null
To fix OP's code, just add parenthesis - in this way the operations will be performed in the correct order and the result will be as expected:
System.out.println("Result is: " + (names == null ? null : names.size()));

you are writing "Result is: " + names which is not equivalent to null so its trying to print names.size(). But when names.size() is called it throw null pointer exception as names is still null.
Modify
System.out.println("Result is: " + names == null ? null : names.size());
to
System.out.print("Result is: ");
System.out.println( names == null ? null : names.size());
then you will get null as output.

Related

Conditionally executed blocks should be reachable

sonar complain Ternary operators should not be nested.
Is there any way possible to remove this complaint since I am beginner in java I would like some help in this issue.
object form = null;
if(objs.getForm() != null)
form = objs.getForm();
String getName = form != null
? referenceObjType + form.getName()
: "" + (objs.getType() == null ? ""
: "(" //$NON-NLS-1$
+ objs.Type().getTypeName() + ")"
+ objs.getName());
What about something like this? Nested ternary operators are quite bad practice.
String getName= "";
if (form != null) {
getName = referenceObjType + form.getName();
} else {
getName = objs.getType() == null ? "" : String.format("(%s)%s",objs.Type().getTypeName(), objs.getName());
}
You need to use parenthesis to group the second ternary operator:
String getName = form != null
? referenceObjType + form.getName()
: "" + (objs.getType() == null ? ""
: "(" //$NON-NLS-1$
+ objs.Type().getTypeName() + ")"
+ objs.getName());
In java the additive operator (+) has a higher preference than the equality operator (==).
see: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/operators.html
So without the parenthesis the statement
"" + objs.getType() == null
The String concatenation is done first and the result then checked against null. Since an empty String that you append something to cannot be null, this statement will always yield false and one part of your ternary operator will never be reachable.
If you are a beginner with Java I would refrain from using ternary operators so you could really understand what each statement is doing.
The issue:
I believe the else statements (the ones starting with ":") are not reachable because form will never be null. Also you are appending a string prior to checking if it is null. This will always return that it is not null.
You also need to group your second ternary operator with a parentheses like so:
String getName = form != null
? referenceObjType + form.getName()
: "" + (objs.getType() == null ? ""
: "(" //$NON-NLS-1$
+ objs.Type().getTypeName() + ")"
+ objs.getName());
It is hard to give you a complete answer since I do not know your original problem and cannot see other code but I hope this helps

Selenium Assert Equals to Value1 or Value2

I want to test in Selenium (Java, Testng)
If my actual value is equal to one of the two values because my value can be Value1 or Value2 and both values will be correct.
If I want to assert only one equality I use this construction:
String expectedPopUpV1 = "Value1";
String expectedPopUpV2 = "Value2";
String actualPopUp = driver.findElement(By.cssSelector(Value)).getText();
Assert.assertEquals(actualPopUp,expectedPopUp);
but what should I do if I want to make something like
Assert.assertEquals(actualPopUp,expectedPopUp1||expectedPopUp1);
You can use assertTrue(boolean condition, String message) for this and give the details in the message
boolean isEqual = actualPopUp.equals(expectedPopUpV1) || actualPopUp.equals(expectedPopUpV2);
Assert.assertTrue(isEqual, "The text " + actualPopUp + " is not " + expectedPopUpV1 + " or " + expectedPopUpV2);
below option should also work using ternary operator:
Assert.assertEquals(expectedPopUpV1.equalsIgnoreCase(actualPopUp )?expectedPopUpV1:expectedPopUpV2 , actualPopUp );
There isn't any such method available. The two closest options I can think of:
if(!actualPopUp.equals(expectedPopUp1) || !actualPopUp.equals(expectedPopUp2) {
Assert.fail("insert failure messsage here");
}
or
if(actualPopUp.equals(expectedPopUp1) || actualPopUp.equals(expectedPopUp2) {
Assert.assertTrue("insert message");
}
The other option would be to really extend the Assert capability by constructing your own with a Builder pattern to be in the tune of:
AssertBuilder.with(actualPopUp).equals(expectedPopUp1).or(expectedPopUp2);
But that may be too complicated for a simple use case.

Runtime boolean and String error in java?

Hi that println giving me error but it working fine if I just print them separately. Any Idea why this happening?
class StringTesting
{
public static void main(String me[])
{
String s1="Varun";
String s2="varun";
String s3="Varun";
String s4=new String("Varun");
String s5=new String("Varun");
System.out.println(" "+s1==s3+" "+s1==s2+" ");//here its giving me error
}
}
And also thanks in Advance :)
In terms of operators, + has the precedence on ==.
It means that this code :
" "+s1==s3+" "+s1==s2+" "
is translated by the compiler by something like that :
" Varun"=="Varun Varun"=="Varun "
the first part " Varun"=="Varun Varun" produces a boolean
and applying to it the "Varun " String with the == comparator, it results to :
booleanExpression == "Varun "
Comparing boolean with a String is not valid.
Anyway, even if it was, you don't want to as you want to output the boolean result of the == comparison between the objects.
So just put between parentheses the == comparisons to indicate to the compiler that operations in have to be evaluated together :
" "+(s1==s3)+" "+(s1==s2)+" "
It will produce a valid concatenation :
String + boolean + String + boolean + String
According to the Java documentation on String, the proper way to compare two strings is by using the .equals method.
System.out.println("s1 == s2 ?: " + s1.equals(s2))
By using the == operator between two Objects you are comparing memory locations, not the actual primitive value(s) contained in the object.
You can't compare booleans and strings using == and this is what is indeed happening there because of the order of operators being applied.
You can fix that using simple brackets:
System.out.println(" " + (s1 == s3) + " " + (s1 == s2) + " ");
Of course, if you do not combine results of two different operators, that will work just fine:
System.out.println(s1 == s3);
So, it was enough to just read the compilation error.

Strange Behavior of Empty String in JAVA [duplicate]

This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 7 years ago.
I am working on a Existing code and i found a Strange Behavior while checking a String is null or Empty. The existing code :
System.out.println("Length: " + value.length());
if (value != null && value != "") {
//code
}
Output:
Length: 0
But the if statement becomes true and its executing the code.
When i replaced the if statement with this one:
if (value != null && value.length() > 0) {
//code
}
It works perfectly. Any idea why the previous one failed and Why value != "" returns true?
Try to use equals method like this:
if (value != null && !"".equals(value)) {
Strings are not compared like this:
value != ""
Use equals:
!"".equals(value)
or isEmpty:
!value.isEmpty()
Because String is immutable
You should compare with value.isEmpty(). According to the source code, it will also compare the length.
What you are doing with != is comparing references, not equality.
When using == you are comparing the references which are not equal, that's why the expression evaluates to true.
You can use StringUtils.isNotEmpty
if (StringUtils.isNotEmpty(value)) {
...
}
true - if the String is not empty and not null
Reference
String is an Object in java, so you can't use == and != with it, because == and != comparing references, which is not equal. Use "".equals(value)
This is because you might have created value variable using new operator:
String value = new String();
So now if you use following :
System.out.println("Length: " + value.length());
if (value != null && value != "") {
System.out.println("hi")
}
It will print hi as value is from heap and literal "" is from string pool and you are making reference comparison. Use equals method instead .
value != ""
check for reference equality not the value equality.
if value is created like this:
String value=new String("");
then there is a high chance that the condition will fail.
For example if you have another String value2
String value2=new String("");
then
value==value2 // is false.
Have a look at this How do I compare strings in Java?
Your best bet is to use value != null && !value.isEmpty(), although you can ace this with the Yoda Expression
"".equals(value)
which saves you typing out the explicit check for null.
You can't use == since that would compare the object reference values (which might be different even if the string looks the same), not the string contents.

String concatenation and + operator [duplicate]

This question already has answers here:
String concatenation: concat() vs "+" operator
(12 answers)
Closed 8 years ago.
I was trying out string concatenation and the '+' operator on a string and encountered the following-
String xyz = "Hello" + null;
System.out.println("xyz= " +xyz);
String abc= "Hello".concat(null);
System.out.println("abc= " +abc);
The output for the first one was : Hellonull
The output for the second one was a Null Pointer exception
I don't understand why there were two different outputs.
When you concatenate null by + operator, it is always converted to "null" String. This explains the first output Hellonull.
The concat function looks internally like this:
public String concat(String s) {
int i = s.length();
if (i == 0) {
return this;
} else {
char ac[] = new char[count + i];
getChars(0, count, ac, 0);
s.getChars(0, i, ac, count);
return new String(0, count + i, ac);
}
}
Source: String concatenation: concat() vs "+" operator
As you can see, it calls s.length(), which in your case means null.length(); which causes the NullPointerException for your String abc= "Hello".concat(null); statement.
Edit: I just decompiled my own String.concat(String s) function and its implementation looks a little bit different, but the reason for the NullPointerException stays the same.
From Docs
If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l).
Otherwise, the conversion is performed as if by an invocation of the toString method of the referenced object with no arguments; but if the result of invoking the toString method is null, then the string "null" is used instead.
"Hello" + null returns the same result as "Hello".concat(String.valueOf(null)).
String.valueOf(null) returns the string "null".
/**
* Concatenates this string and the specified string.
*
* #param string
* the string to concatenate
* #return a new string which is the concatenation of this string and the
* specified string.
*/
public String concat(String string) {
if (string.count > 0 && count > 0) {
char[] buffer = new char[count + string.count];
System.arraycopy(value, offset, buffer, 0, count);
System.arraycopy(string.value, string.offset, buffer, count, string.count);
return new String(0, buffer.length, buffer);
}
return count == 0 ? string : this;
}
the source code's first line in contact function calls the null's count. So it will throw Null Pointer exception.
Calling concat() on a null reference gives NPE, hence different results as "+" operator treats null reference as "null".

Categories

Resources