This might be a very basic question, but I still don't know the answer.
String abc = null;
System.out.println(abc);
Why does System.out.println print "null" and does not throw NullPointerException?
It's behaving as it's documented to. PrintStream.println(String) is documented as:
Prints a String and then terminate the line. This method behaves as though it invokes print(String) and then println().
PrintStream.print(String) is documented as:
Prints a string. If the argument is null then the string "null" is printed. Otherwise, the string's characters are converted into bytes according to the platform's default character encoding, and these bytes are written in exactly the manner of the write(int) method.
When in doubt, read the documentation :)
Because it eventually reaches the print method, which prints "null" for a null String :
public void println(String x) {
synchronized (lock) {
print(x);
println();
}
}
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
The same behavior exists for printing of any null reference (in this case the "null" String is returned by String.valueOf(null) :
public void println(Object x) {
String s = String.valueOf(x);
synchronized (lock) {
print(s);
println();
}
}
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
You can just have a look at PrintStream source code:
public void println(String x) {
synchronized (this) {
print(x);
newLine();
}
}
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
As you can see, the null case is handled by just printing "null".
Null is special cased inside the print function:
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
According to PrintStream#println()
Prints an Object and then terminate the line. This method calls at first String.valueOf(x) to get the printed object's string value, then behaves as though it invokes print(String) and then println().
According to String#valueOf
Returns the string representation of the Object argument.
If the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.
System.out.print function source code. If print string is null ,it sets to "null"
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
Well in some circumstances, System.out.println could throw a NullPointerException making you think that is how it works.
If you have a complex object where you have created your own toString() method, there is a potential for the error to occur within that method. You could either accidentally or purposely code that such that the NPE does occur. The object itself is not null, however some of the attributes inside might be null.
Such coding should most likely be discouraged though because it does break the contract as others have pointed out. The desired behavior is to represent a null object as null and not NPE being thrown.
Related
I have a test cases as below:
#Test
public void GIVEN_correct_tradingStatusId_parameter_WHEN_invoked_getTradingStatusByName_THEN_correct_TradingStatus_is_returned() {
String tradingStatus = lookupDto.getTradingStatusByName("2013");
assertNotNull(tradingStatus);
assertEquals("Dissolved", tradingStatus);
}
Here I am testing for tradingStatus not to be null and then checking it equals to Dissolved.
My concern is do I actually need to test assertNotNull if I am testing using assertEquals.
I went through the method definition for assertEquals in sourcecode. It is as below:-
static public void assertEquals(String message, Object expected,
Object actual) {
if (equalsRegardingNull(expected, actual)) {
return;
} else if (expected instanceof String && actual instanceof String) {
String cleanMessage = message == null ? "" : message;
throw new ComparisonFailure(cleanMessage, (String) expected,
(String) actual);
} else {
failNotEquals(message, expected, actual);
}
}
In this equalsRegardingNull is like :
private static boolean equalsRegardingNull(Object expected, Object actual) {
if (expected == null) {
return actual == null;
}
return isEquals(expected, actual);
}
I am not able to understand even from this whether it is worth to use assertNotNull before calling assertEquals. Please help.
The short answer is NO.
No there is no need to use assertNotNull before assertEquals. If your tradingStatus is null the comparison will anyway fail and will tell you that you are comparing against null. Everything else makes your test code just more complex but brings no extra benefit in return.
You should try to dig deep isEqual method, you will find:
private static boolean isEquals(Object expected, Object actual) {
return expected.equals(actual);
}
so you will find it's comparing by using expected.equals method, and since expected checks null firstly, by:
if (expected == null) {
return actual == null;
}
and it avoids the NullPointerException in expected.equals, it's safe to compare.
So it's unnecessary to manually check actual(tradingStatus) null by assertNotNull(tradingStatus);.
How can I check whether a string is not null and not empty?
public void doStuff(String str)
{
if (str != null && str != "**here I want to check the 'str' is empty or not**")
{
/* handle empty string */
}
/* ... */
}
What about isEmpty() ?
if(str != null && !str.isEmpty())
Be sure to use the parts of && in this order, because java will not proceed to evaluate the second part if the first part of && fails, thus ensuring you will not get a null pointer exception from str.isEmpty() if str is null.
Beware, it's only available since Java SE 1.6. You have to check str.length() == 0 on previous versions.
To ignore whitespace as well:
if(str != null && !str.trim().isEmpty())
(since Java 11 str.trim().isEmpty() can be reduced to str.isBlank() which will also test for other Unicode white spaces)
Wrapped in a handy function:
public static boolean empty( final String s ) {
// Null-safe, short-circuit evaluation.
return s == null || s.trim().isEmpty();
}
Becomes:
if( !empty( str ) )
Use org.apache.commons.lang.StringUtils
I like to use Apache commons-lang for these kinds of things, and especially the StringUtils utility class:
import org.apache.commons.lang.StringUtils;
if (StringUtils.isNotBlank(str)) {
...
}
if (StringUtils.isBlank(str)) {
...
}
Just adding Android in here:
import android.text.TextUtils;
if (!TextUtils.isEmpty(str)) {
...
}
To add to #BJorn and #SeanPatrickFloyd The Guava way to do this is:
Strings.nullToEmpty(str).isEmpty();
// or
Strings.isNullOrEmpty(str);
Commons Lang is more readable at times but I have been slowly relying more on Guava plus sometimes Commons Lang is confusing when it comes to isBlank() (as in what is whitespace or not).
Guava's version of Commons Lang isBlank would be:
Strings.nullToEmpty(str).trim().isEmpty()
I will say code that doesn't allow "" (empty) AND null is suspicious and potentially buggy in that it probably doesn't handle all cases where is not allowing null makes sense (although for SQL I can understand as SQL/HQL is weird about '').
str != null && str.length() != 0
alternatively
str != null && !str.equals("")
or
str != null && !"".equals(str)
Note: The second check (first and second alternatives) assumes str is not null. It's ok only because the first check is doing that (and Java doesn't does the second check if the first is false)!
IMPORTANT: DON'T use == for string equality. == checks the pointer is equal, not the value. Two strings can be in different memory addresses (two instances) but have the same value!
Almost every library I know defines a utility class called StringUtils, StringUtil or StringHelper, and they usually include the method you are looking for.
My personal favorite is Apache Commons / Lang, where in the StringUtils class, you get both the
StringUtils.isEmpty(String) and the
StringUtils.isBlank(String) method
(The first checks whether a string is null or empty, the second checks whether it is null, empty or whitespace only)
There are similar utility classes in Spring, Wicket and lots of other libs. If you don't use external libraries, you might want to introduce a StringUtils class in your own project.
Update: many years have passed, and these days I'd recommend using Guava's Strings.isNullOrEmpty(string) method.
This works for me:
import com.google.common.base.Strings;
if (!Strings.isNullOrEmpty(myString)) {
return myString;
}
Returns true if the given string is null or is the empty string.
Consider normalizing your string references with nullToEmpty. If you
do, you can use String.isEmpty() instead of this method, and you won't
need special null-safe forms of methods like String.toUpperCase
either. Or, if you'd like to normalize "in the other direction,"
converting empty strings to null, you can use emptyToNull.
There is a new method in java-11: String#isBlank
Returns true if the string is empty or contains only white space codepoints, otherwise false.
jshell> "".isBlank()
$7 ==> true
jshell> " ".isBlank()
$8 ==> true
jshell> " ! ".isBlank()
$9 ==> false
This could be combined with Optional to check if string is null or empty
boolean isNullOrEmpty = Optional.ofNullable(str).map(String::isBlank).orElse(true);
String#isBlank
How about:
if(str!= null && str.length() != 0 )
Returns true or false based on input
Predicate<String> p = (s)-> ( s != null && !s.isEmpty());
p.test(string);
Use Apache StringUtils' isNotBlank method like
StringUtils.isNotBlank(str)
It will return true only if the str is not null and is not empty.
For completeness: If you are already using the Spring framework, the StringUtils provide the method
org.springframework.util.StringUtils.hasLength(String str)
Returns:
true if the String is not null and has length
as well as the method
org.springframework.util.StringUtils.hasText(String str)
Returns:
true if the String is not null, its length is greater than 0, and it does not contain whitespace only
You can use the functional style of checking:
Optional.ofNullable(str)
.filter(s -> !(s.trim().isEmpty()))
.ifPresent(result -> {
// your query setup goes here
});
You should use org.apache.commons.lang3.StringUtils.isNotBlank() or org.apache.commons.lang3.StringUtils.isNotEmpty. The decision between these two is based on what you actually want to check for.
The isNotBlank() checks that the input parameter is:
not Null,
not the empty string ("")
not a sequence of whitespace characters (" ")
The isNotEmpty() checks only that the input parameter is
not null
not the Empty String ("")
If you don't want to include the whole library; just include the code you want from it. You'll have to maintain it yourself; but it's a pretty straight forward function. Here it is copied from commons.apache.org
/**
* <p>Checks if a String is whitespace, empty ("") or null.</p>
*
* <pre>
* StringUtils.isBlank(null) = true
* StringUtils.isBlank("") = true
* StringUtils.isBlank(" ") = true
* StringUtils.isBlank("bob") = false
* StringUtils.isBlank(" bob ") = false
* </pre>
*
* #param str the String to check, may be null
* #return <code>true</code> if the String is null, empty or whitespace
* #since 2.0
*/
public static boolean isBlank(String str) {
int strLen;
if (str == null || (strLen = str.length()) == 0) {
return true;
}
for (int i = 0; i < strLen; i++) {
if ((Character.isWhitespace(str.charAt(i)) == false)) {
return false;
}
}
return true;
}
test equals with an empty string and null in the same conditional:
if(!"".equals(str) && str != null) {
// do stuff.
}
Does not throws NullPointerException if str is null, since Object.equals() returns false if arg is null.
the other construct str.equals("") would throw the dreaded NullPointerException. Some might consider bad form using a String literal as the object upon wich equals() is called but it does the job.
Also check this answer: https://stackoverflow.com/a/531825/1532705
Simple solution :
private boolean stringNotEmptyOrNull(String st) {
return st != null && !st.isEmpty();
}
As seanizer said above, Apache StringUtils is fantastic for this, if you were to include guava you should do the following;
public List<Employee> findEmployees(String str, int dep) {
Preconditions.checkState(StringUtils.isNotBlank(str), "Invalid input, input is blank or null");
/** code here **/
}
May I also recommend that you refer to the columns in your result set by name rather than by index, this will make your code much easier to maintain.
You can use StringUtils.isEmpty(), It will result true if the string is either null or empty.
String str1 = "";
String str2 = null;
if(StringUtils.isEmpty(str)){
System.out.println("str1 is null or empty");
}
if(StringUtils.isEmpty(str2)){
System.out.println("str2 is null or empty");
}
will result in
str1 is null or empty
str2 is null or empty
I've made my own utility function to check several strings at once, rather than having an if statement full of if(str != null && !str.isEmpty && str2 != null && !str2.isEmpty). This is the function:
public class StringUtils{
public static boolean areSet(String... strings)
{
for(String s : strings)
if(s == null || s.isEmpty)
return false;
return true;
}
}
so I can simply write:
if(!StringUtils.areSet(firstName,lastName,address)
{
//do something
}
In case you are using Java 8 and want to have a more Functional Programming approach, you can define a Function that manages the control and then you can reuse it and apply() whenever is needed.
Coming to practice, you can define the Function as
Function<String, Boolean> isNotEmpty = s -> s != null && !"".equals(s)
Then, you can use it by simply calling the apply() method as:
String emptyString = "";
isNotEmpty.apply(emptyString); // this will return false
String notEmptyString = "StackOverflow";
isNotEmpty.apply(notEmptyString); // this will return true
If you prefer, you can define a Function that checks if the String is empty and then negate it with !.
In this case, the Function will look like as :
Function<String, Boolean> isEmpty = s -> s == null || "".equals(s)
Then, you can use it by simply calling the apply() method as:
String emptyString = "";
!isEmpty.apply(emptyString); // this will return false
String notEmptyString = "StackOverflow";
!isEmpty.apply(notEmptyString); // this will return true
If you are using Spring Boot then below code will do the Job
StringUtils.hasLength(str)
With Java 8 Optional you can do:
public Boolean isStringCorrect(String str) {
return Optional.ofNullable(str)
.map(String::trim)
.map(string -> !str.isEmpty())
.orElse(false);
}
In this expression, you will handle Strings that consist of spaces as well.
To check if a string is not empty you can check if it is null but this doesn't account for a string with whitespace. You could use str.trim() to trim all the whitespace and then chain .isEmpty() to ensure that the result is not empty.
if(str != null && !str.trim().isEmpty()) { /* do your stuffs here */ }
I would advise Guava or Apache Commons according to your actual need. Check the different behaviors in my example code:
import com.google.common.base.Strings;
import org.apache.commons.lang.StringUtils;
/**
* Created by hu0983 on 2016.01.13..
*/
public class StringNotEmptyTesting {
public static void main(String[] args){
String a = " ";
String b = "";
String c=null;
System.out.println("Apache:");
if(!StringUtils.isNotBlank(a)){
System.out.println(" a is blank");
}
if(!StringUtils.isNotBlank(b)){
System.out.println(" b is blank");
}
if(!StringUtils.isNotBlank(c)){
System.out.println(" c is blank");
}
System.out.println("Google:");
if(Strings.isNullOrEmpty(Strings.emptyToNull(a))){
System.out.println(" a is NullOrEmpty");
}
if(Strings.isNullOrEmpty(b)){
System.out.println(" b is NullOrEmpty");
}
if(Strings.isNullOrEmpty(c)){
System.out.println(" c is NullOrEmpty");
}
}
}
Result:
Apache:
a is blank
b is blank
c is blank
Google:
b is NullOrEmpty
c is NullOrEmpty
Simply, to ignore white space as well:
if (str == null || str.trim().length() == 0) {
// str is empty
} else {
// str is not empty
}
Consider the below example, I have added 4 test cases in main method. three test cases will pass when you follow above commented snipts.
public class EmptyNullBlankWithNull {
public static boolean nullEmptyBlankWithNull(String passedStr) {
if (passedStr != null && !passedStr.trim().isEmpty() && !passedStr.trim().equals("null")) {
// TODO when string is null , Empty, Blank
return true;
}else{
// TODO when string is null , Empty, Blank
return false;
}
}
public static void main(String[] args) {
String stringNull = null; // test case 1
String stringEmpty = ""; // test case 2
String stringWhiteSpace = " "; // test case 3
String stringWhiteSpaceWithNull = " null"; // test case 4
System.out.println("TestCase result:------ "+nullEmptyBlankWithNull(stringWhiteSpaceWithNull));
}
}
BUT test case 4 will return true(it has white space before null) which is wrong:
String stringWhiteSpaceWithNull = " null"; // test case 4
We have to add below conditions to make it work propper:
!passedStr.trim().equals("null")
If you use Spring framework then you can use method:
org.springframework.util.StringUtils.isEmpty(#Nullable Object str);
This method accepts any Object as an argument, comparing it to null and the empty String. As a consequence, this method will never return true for a non-null non-String object.
To check on if all the string attributes in an object is empty(Instead of using !=null on all the field names following java reflection api approach
private String name1;
private String name2;
private String name3;
public boolean isEmpty() {
for (Field field : this.getClass().getDeclaredFields()) {
try {
field.setAccessible(true);
if (field.get(this) != null) {
return false;
}
} catch (Exception e) {
System.out.println("Exception occurred in processing");
}
}
return true;
}
This method would return true if all the String field values are blank,It would return false if any one values is present in the String attributes
I've encountered a situation where I must check that "null" (as a string) must be regarded as empty. Also white space and an actual null must return true.
I've finally settled on the following function...
public boolean isEmpty(String testString) {
return ((null==testString) || "".equals((""+testString).trim()) || "null".equals((""+testString).toLowerCase()));
}
I got this piece of code from a commercial product. I believe that it will always throw the java.lang.NullPointerException exception when this.result is null. Am I right to say that?
private void closeCurrentResult() throws SQLException {
this.lastUpdateCount = -1;
if(this.result != null) {
this.result.close();
}
this.result = null;
}
if this.result is null, then
this.result = null
is equivalent to
null = null;
while causes the NPE.
After read through some of the replies, I think the thing becomes clear. I also did a test as the code shown below:
public class NullTest {
public static void main(String[] args) {
ABC a = new ABC(null);
a.test();
}
static class ABC {
Object result;
ABC(Object result) {
this.result = result;
}
void test() {
if (this.result != null) {
System.out.println("do something");
}
this.result = null;
}
}
}
And it works just fine.
Let's go through it step by step:
first this.lastUpdateCount = -1; does nothing but setting a global member variable to -1.
if(this.result != null)
This one (guard clause) tests, whether result is null if not so this.result.close(); the close() method on result is called. The guard says, it's safe to do so. After that this.result = null; sets result to null anyways.
After this codeblock, two things are assured:
1) this.result is null
2) And if this.result had something open it is now close
if this.result is null, then this.result = null is equivalent to null = null;
this.result = is an assignment statement: You are assigning something to this.result, whose value may be null. This operation is NPE-safe.
No..
this.result = null simply assigns null reference to this.result.
It will throw NPE only when this == null, which is...never.
NPE means you invoked a method or referred a property on a null reference. That is to say, when your code is like this:
obj.someProperty or obj.someMethod() when obj itself is null.
BTW, null reference is a special reference (instead of a special value or some compile-time mechanism).
All the null reference is identical (same reference).
String a = null;
Person p = null;
assert a == b;
null reference is the "default value" for reference-type variables.
class Person{
String name; // `name` is null until assigned otherwise.
}
NPE will be thrown when unboxing a null reference variable.
Integer a = null;
int b = a; // throws NPE.
Many JDK methods threat null reference specially.(Which is good and bad.)
String a = null;
System.out.println(a);
// will NOT throw NPE because:
// PrintStream.java:
public void println(String var1) {
synchronized(this) {
this.print(var1);
this.newLine();
}
}
Another example:
String b = null;
String a = String.valueOf(b);
// a is String "null" instead of null reference. Because:
// String.java:
public static String valueOf(Object var0) {
return var0 == null?"null":var0.toString();
}
No, you are not.
This:
if(this.result != null) {
this.result.close();
}
Call close() only if this.result is not null, correct.
This would have thrown a NullPointerException if the check would have been this.result != null.
The last line:
this.result = null;
Simply set this.result as null, nothing wrong here either.
The result is like a label to a memory address. When result is not null, it's pointing to some memory address where there is an object.
When you use the assignment operator =, as in result = null, you're saying, "make result point to null and I don't care what it was originally pointing at". So whatever result is currently pointing to does not matter, even if it's null, reassigning result to null will not throw a NPE.
The code you posted won't throw a null pointer exception. But after setting the result as null you try to access any method it will throw a null pointer exception.
private void closeCurrentResult() throws SQLException {
this.lastUpdateCount = -1;
if(this.result != null) {
this.result.close();
}
this.result = null;
this.result.someMethod(); //Will throw a Null Pointer Exception
}
Is it possible to wrap following code in a reusable function?
EDIT: this is just an example, I want a working solution for ALL recursion depths
what I want is that following code is generated:
if (MyObject o == null ||
o.getSubObject() == null ||
o..getSubObject().getSubSubObject() == null /*||
... */)
return defaultValue;
return o.getSubObject().getSubObject()/*...*/.getDesiredValue();
by calling something like
Object defaultValue = null;
Object result = NullSafeCall(o.getSubObject().getSubObject()/*...*/.getDesiredValue(), defaultValue);
The seond code block is just an idea, I don't care how it looks like, all I want is that I, if desired, can avoid all the null checks before calling a deeper function...
Injection could do this propably, but is there no other/easier solution? Never looked at injection before yet...
EDIT2: example in another language: http://groovy.codehaus.org/Operators#Operators-SafeNavigationOperator
Not really, any code you would write this way would look horrible and/or use very slow reflection. Unless you use an actual Java preprocessor that can understand and change the code you've written.
A better (but associated with quite a bit of refactoring) approach would be to make sure that the values in question cannot possibly be null. For example, you could modify the individual accessors (getSubObject(), getDesiredValue()) to never return null in the first place: make them return default values. The accessors on the default values return default values in turn.
Java8 helps to get the closest you'll get to your syntax with decent performance I suspect;
// Evaluate with default 5 if anything returns null.
int result = Optional.eval(5, o, x->x.getSubObject(), x->x.getDesiredValue());
This can be done with this utility class;
class Optional {
public static <T, Tdef, T1> Tdef eval(Tdef def, T input, Function<T,T1> fn1,
Function<T1, Tdef> fn2)
{
if(input == null) return def;
T1 res1 = fn1.apply(input);
if(res1 == null) return def;
return fn2.apply(res1);
}
}
Sadly, you'll need a separate eval() defined per number of method calls in the chain, so you may want to define a few, but compile time type safe and reusable with just about any calls/types.
You can do something like this
public static Object NullSafeCall(MyObject o,Object defaultValue){
if ( o == null || o.getSubObject() == null)
{
return defaultValue;
}
else
{
return o.getSubObject().getDesiredValue();
}
}
Now you can call this method as follows
Object result = NullSafeCall(o, defaultValue);
i would suggest just replace
Object result = NullSafeCall(o.getSubObject().getDesiredValue(), defaultValue);
by the
Object result = (o == null || o.subObject == null) ? defaultVlue : o.getSubObject().getDesiredValue();
Create method only if you can reuse it......
What you want is not possible. It is essential to understand that using this syntax: Object result = NullSafeCall(o.getSubObject().getSubObject() ...); the part of o.getSubObject().getSubObject() will be evaluated before any control passes to the function/method thus throwing the exception.
It is required to have some type of context before executing such code. The closest to this I could think of, can be done using anonymous inner classes like the example below:
// intended to be implemented by an anonymous inner class
interface NullSafeOperation<T> {
public T executeSafely();
};
// our executor that executes operations safely
public static class NullSafeExecutor<T> {
public NullSafeExecutor() {}
public T execute(T defaultValue, NullSafeOperation<T> nso) {
T result = defaultValue;
try {
result = nso.executeSafely();
} catch(NullPointerException e) {
// ignore
}
return result;
}
// utility method to create a new instance and execute in one step
public static <T> T executeOperation(T defaultValue, NullSafeOperation<T> nso) {
NullSafeExecutor<T> e = new NullSafeExecutor<T>();
T result = e.execute(defaultValue, nso);
return result;
}
}
public static void main(String[] args) {
final String aNullString = null;
String result = NullSafeExecutor.executeOperation("MyDefault", new NullSafeOperation<String>() {
#Override
public String executeSafely() {
// trying to call a method on a null string
// it will throw NullPointerException but it will be catched by the executor
return aNullString.trim();
}
});
System.out.println("Output = " + result); // prints: Output = MyDefault
}
How come?
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append((String)null);
sb.append(" World!");
Log.d("Test", sb.toString());
Produces
06-25 18:24:24.354: D/Test(20740): Hellonull World!
I expect that appending a null String will not append at all!!
BTW, the cast to String is necessary because StringBuilder.append() has a lot of overloaded versions.
I simplified my code to make a point here, in my code a got a method returning a string
public String getString() { ... }
...
sb.append(getString());
...
getString() sometimes returns null; now I have to test it if I want to use a StringBuilder!!!!
Furthermore, let's clarify my question here: how can I get StringBuilder.append() to accept, in an elegant way, a null string, and not convert it to the literal string "null".
By elegant I mean I don't want to get the string, test if it is null and only then append it. I am looking for an elegant oneliner.
How come?
Its clearly written in docs
The characters of the String argument are appended, in order, increasing the length of this sequence by the length of the argument. If str is null, then the four characters "null" are appended.
So please put a null check before append.
That's just the way it is. null is appended as "null". Similarly, when you print null with System.out.println(null) you print "null".
The way to avoid that is that method that returns string getString() checks for null:
public String getString() {
...
if (result == null) {
return "";
}
}
It behaves like this, because null isn't an empty String as you think of it. Empty Stringwould be new String("");. Basically append() method appends "null" if it gets null value as a parameter.
EDIT
My previous answer was not reflecting the appropriate reason for such behaviour of StringBuilder as asked by OP. Thanks to #Stephen C for pointing out that
I expect that appending a null String will not append at all!!
But it is appending. The reason for such behaviour of StringBuilder is hidden in implementation detail of append(Object obj) method which takes us to AbstractStringBuilder#append(String str) method which is defined as follows:
public AbstractStringBuilder append(String str) {
if (str == null) str = "null"; -->(1)
//.......
return this;
}
It clearly specifying that if the input String is null then it is changed to String literal "null" and then it processes further.
How can I get StringBuilder.append() to accept, in an elegant way, a null string, and not convert it to the literal string "null".
You need to check the given String for null explicitly and then proceed. For example:
String s = getString();
StringBuffer buf = new StringBuffer();
//Suppose you want "Hello "<value of s>" world"
buf.append("Hello ");
buf.append(s==null?" world" : s+" world");
AbstractStringBuilder class appends an object through String.valueOf(obj) method which in turn converts NULL into string literal "null". Therefor there is no inbuilt method to help you here. You have to either use ternary operator within append method or write a utility method to handle it, as others suggested.
This will work for you
public static String getString(StringBuilder sb, String str) {
return sb.append(str == null ? "" : str).toString();
}
What about writing an utility method like
public static void appendString(StringBuilder sb, String st) {
sb.append(st == null ? "" : st);
}
or this the ternary operator is very handy.
String nullString = null;
StringBuilder sb = new StringBuilder();
sb.append("Hello");
if (nullString != null) sb.append(nullString);
sb.append(" World!");
Log.d("Test", sb.toString());
There! I did it in one line :)
One line?
sb.append((getString()!=null)?getString():"");
done. But is pointless as have to call getString() twice
As was suggested build check into getString() method
You can also write decorator for StringBuilder, which can check whatever you want:
class NotNullStringBuilderDecorator {
private StringBuilder builder;
public NotNullStringBuilderDecorator() {
this.builder = new StringBuilder();
}
public NotNullStringBuilderDecorator append(CharSequence charSequence) {
if (charSequence != null) {
builder.append(charSequence);
}
return this;
}
public NotNullStringBuilderDecorator append(char c) {
builder.append(c);
return this;
}
//Other methods if you want
#Override
public String toString() {
return builder.toString();
}
}
Example of usage:
NotNullStringBuilderDecorator sb = new NotNullStringBuilderDecorator();
sb.append("Hello");
sb.append((String) null);
sb.append(" World!");
System.out.println(sb.toString());
With this solution you have not to change POJO classes.