Related
Consider the usage of this expression:
String hi = Optional.ofNullable(sayHi()).orElse("-");
which effectively corresponds to this ternary expression:
String hi = sayHi() != null ? sayHi() : "-";
Is this usage of Optional.ofNullable with a method call a good practice? Or just extra verbose coding?
I recognise that Optional.ofNullable actually creates a variable and avoids calling the sayHi() method twice. To avoid this problem you actually could create an extra variable but this adds to the verbosity of the ternary option:
String hi = sayHi();
hi = hi != null ? hi : "-";
On the other hand Optional.ofNullable creates in case of hi not being null an extra Optional object. So there is for sure more overhead to it.
So there seem to be some pros and cons to using this type of construct to replace the ternary constructor.
By the way: this is the Java 8 implementation of Optional.ofNullable:
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
In JDK 9 or later, use this:
String hi = Objects.requireNonNullElse(sayHi(), "-");
This avoids having to repeat sayHi() if a ternary operator is used, or to assign its value to a local variable that is reused within the ternary. It might be a small improvement. It also sidesteps the question of whether to use Optional. :-)
Whenever I come to think of using the Optional API for a specific purpose I always remind my self of what it was intended to do and why it was brought into the JDK and i.e.
Optional in intended to provide a limited mechanism for library method
return types where there is a clear need to represent “no result” and
where using null for this is overwhelmingly likely to cause errors - Stuart Marks
Optional is primarily focused on a return type that might or might not have a return value.
Over using this construct like in this specific example of yours just causes extra memory allocation and GC overhead.
I’d keep things simple and instead do:
String hi = sayHi();
if(hi == null) hi = “-“;
...
Is this usage of Optional.ofNullable with a method call a good practice?
Conceptually, it's a bad practice. The basic idea is to represent the absence of a return value, not to wrap everything that might be null. I am strongly against this usage.
Or just extra verbose coding?
It looks to me like a failed attempt to make your code more fashionable. ("Look, we are using brand-new Optional from Java 8!")
I prefer readability and clarity over conciseness.
This Optinal usage doesn't provide clarity but raises questions:
Why do you wrap the variable?
What are you going to do with this Optional?
Will it be used/returned below?
It doesn't give brevity either: your second line is even shorter.
To avoid this problem you actually could create an extra variable but this adds to the verbosity of the ternary option.
You aren't creating an extra variable. The one-line version could be:
String hi = (hi = sayHi()) != null ? hi : "-";
Though, your two-line suggestion is absolutely fine:
String messageContent = sayHi();
String hi = messageContent != null ? messageContent : "-";
If you're going to allow Optional into your workflow then you should consider modifying the sayHi() method so that it returns Optional<String> which will make the result more elegant:
hi = sayHi().orElse("-");
If you don't want to introduce Optional into your workflow (because it does create an additional object to contain the optional value) then you're better off sticking with simple null checks and the ternary operator.
With regard to the performance costs of Optional (such as increased garbage collection), you'd need to profile your application and decide whether or not this was a real concern.
Additionally, if you're mostly interested in String then be aware of the Objects.toString(Object, String) method which return a default value if the object is null:
hi = Objects.toString(hi, "-");
This is tidier and more elegant than writing out the code manually.
In brief: avoid the Optional type.
The main argument for Optional on return types is, "It's too easy for clients to forget to handle the possibility of a null return value. Optional is ugly and in your face, so a client is less likely to forget to handle the possibility of an empty return value. Everywhere else, programmers should continue to use normal references, which might be null."
I wrote a discussion of the pros and cons of using Java's Optional type: Nothing is better than the Optional type.
I think it's mostly a matter of personal taste.
From my point of view it would be more meaningful to just return an Optional<String> and let the caller deal with a missing value.
Optional, being a monadic type, can be leveraged for more then just getting an alt-value.
On the other end your operator seems terse enough, if used consistently it could be practical.
I don't think performance is a big issue here.
I recently saw something in some code that made me curious if it was actually having some kind of optimization or performance impact. It was a line like this in a constants file:
public static final Object NULL = null;
Then, throughout the code, rather than explicitly using the null keyword, it would be referred to with Constants.NULL.
I've seen this kind of thing before with something like:
public static final String EMPTY_STRING = "";
... and that seemed to make at least a little bit of sense, if it's an attempt to avoid creating lots of duplicate "" instances. But does it really make any difference with null, since it's not actually any kind of object? Is there something I'm missing?
Neither makes any sense. Using "" in multiple places in your code does not create multiple instances of a String object. Unless you explicitly call new String(""); the JVM just creates a pool of Strings and references the one instance of each particular String.
I don't think that defining and using NULL in this manner does more than add noise. Perhaps whoever wrote that code came from a C++ background, and preferred the more familiar look of NULL over null.
The second example is also questionable, since using "" many times would not result in a separate String object created for every use. To quote the JLS:
Moreover, a string literal always refers to the same instance of class String. This is because string literals - or, more generally, strings that are the values of constant expressions (§15.28) - are "interned" so as to share unique instances, using the method String.intern.
There is a purpose to use the Object.NULL.
Suppose that you have a bunch of code that validates if your object is null or not. So as part of a new feature, you need to use default values in some cases of null object.
With the simple if obj != null you can't track down the places where you object is validates against nullity. But if you use obj != Object.NULL then you can use your IDE/editor to help you to find those usages.
Does not make any difference in memory occupied due to the string pool concept in java and also it makes the code look more dirty when using NULL constant instead of null or EMPTY_STRING instead of "".
Both of them are self explanatory so there should be no need to create a naming constant for them.
I come from a C#.net background and whenever I had a string I was declaring it as String.Empty
Now I am looking at a Java code from a co-worker and he has declared his strings in a method like this:
String myStr = null;
I don't like it, and even worse, he is assigning values to these strings in an "IF" block where it may or may not even qualify, and then at the end of the method he is calling a myStr.length() on them.
So my question is what is a preferred way in Java? do you think is it better to define them as String.Empty OR leave them as null and do a null check just before calling .length() on them?
In general, using null values is a bad idea, especially if they are returned from a method or passed to another method. Using the Null Object pattern is better, and in a string's case the Null Object is an empty string. By consistently avoiding nulls, the probability of getting a NullPointerException gets smaller and the code becomes more readable (this is discussed at length in Clean Code chapter 7, pages 110-112).
In Java String s = "" does not allocate any memory, because the JVM will have interned the string literal, so there isn't even a performance difference (and even if there were, it would be a premature optimization).
They both have their uses. Empty strings are in-band, i.e. can occur in the input, so they are no use as sentinels. Null is only useful as a sentinel. If you're going to append to it you should initialize it with "" of course. If you're going to immediately reassign it there's no need to provide any value at all, and you should probably combine the declaration with the reassignment. I see far too much of this:
String s = new String();
s = "some string";
All this tells me is that somebody doesn't understand the language.
thought both are applicable for different scenarios, assigning it null will be better(saves memory and less error prone) provided you later on set some string to that else you will be getting a null pointer exception.
An empty String is often a sign that you should either be using a StringBuilder if you're appending (which is a common case). A null reference is 'better' because it uses less memory and it's faster to check if a String is null compared to checking if it's empty. I would advice against using empty Strings instead of declaring them as null, though you should still check for null reference before you use it unless you're 100% sure that it would have been assigned a value at some stage.
As we all know, String is immutable in java. however, one can change it using reflection, by getting the Field and setting access level. (I know it is unadvised, I am not planning to do so, this question is pure theoretical).
my question: assuming I know what I am doing (and modify all fields as needed), will the program run properly? or does the jvm makes some optimizations that rely on String being immutable? will I suffer performance loss? if so, what assumption does it make? what will go wrong in the program
p.s. String is just an example, I am interested actually in a general answer, in addition to the example.
thanks!
After compilation some strings may refer to the one instance, so, you will edit more than you want and never know what else are you editing.
public static void main(String args[]) throws Exception {
String s1 = "Hello"; // I want to edit it
String s2 = "Hello"; // It may be anywhere and must not be edited
Field f = String.class.getDeclaredField("value");
f.setAccessible(true);
f.set(s1, "Doesn't say hello".toCharArray());
System.out.println(s2);
}
Output:
Doesn't say hello
You are definitely asking for trouble if you do this. Does that mean you will definitely see bugs right away? No. You might get away with it in a lot of cases, depending on what you're doing.
Here are a couple of cases where it would bite you:
You modify a string that happens to have been declared as literal somewhere within the code. For example you have a function and somewhere it is being called like function("Bob"); in this scenario the string "Bob" is changed throughout your app (this will also be true of string constants declared as final).
You modify a string which is used in substring operations, or which is the result of a substring operation. In Java, taking a substring of a string actually uses the same underlying character array as the source string, which means modifications to the source string will affect substrings (and vice versa).
You modify a string that happens to be used as a key in a map somewhere. It will no longer compare equal to its original value, so lookups will fail.
I know this question is about Java, but I wrote a blog post a while back illustrating just how insane your program may behave if you mutate a string in .NET. The situations are really quite similar.
The thing that jumps to mind for me is string interning - literals, anything in the constant pool and anything manually intern()ed points to the same string object. If you start messing around with the contents of an interned string literal, you may well see the exact same alterations on all the other literals using the same underlying object.
I'm not sure whether the above actually happens since I've never tried (in theory it will, I don't know if something happens under the scene to stop it but I doubt it) but it's things like that that could throw up potential problems. Of course, it could also throw up problems at the Java level through just passing multiple references to the same string around and then using a reflection attack to alter the object from one of the references. Most people (me included!) won't explicitly guard against that sort of thing in code, so using that attack with any code that's not your own, or your own code if you haven't guarded against that either, could cause all sorts of bizarre, horrible bugs.
It's an interesting area theoretically, but the more you dig around the more you see why anything along these lines is a bad idea!
Speaking outside of string, there's no performance enhancements I know of for an object being immutable (indeed I don't think the JVM can even tell at the moment whether an object is immutable, reflection attacks aside.) It could throw things like the checker-framework off though or anything that tries to statically analyse the code to guarantee it's immutable.
I'm pretty sure The JVM itself makes no assumptions about the immutability of Strings, as "immutability" in Java is not a language-level construct; it's a trait implied by a class's implementation, but cannot, as you note, be actually guaranteed in the presence of reflection. Thus, it also shouldn't be relevant to performance.
However, pretty much all Java code in existence (including the Standard API implementation) relies on Strings being immutable, and if you break that expectation, you'll see all kinds of bugs.
The private fields in the String class are the char[], the offset and length. Changing any of these should not have any adverse effect on any other object. But if you can somehow change the contents of the char[], then you could probably see some surprising side effects.
public static void main(String args[]){
String a = "test213";
String s = new String("test213");
try {
System.out.println(s);
System.out.println(a);
char[] value = (char[])getFieldValue(s, "value");
value[1] = 'a';
System.out.println(s);
System.out.println(a);
} catch (Exception e) {
e.printStackTrace();
}
}
static Object getFieldValue(String s,String fieldName) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Object chars = null;
Field innerCharArray = String.class.getDeclaredField(fieldName);
innerCharArray.setAccessible(true);
chars = innerCharArray.get(s);
return chars;
}
Changing value of S will change the literal of a as mentioned in all answers.
To demonstrate how can it screw up a program:
System.out.print("Initial: "); System.out.println(addr);
editIntStr("ADDR_PLACEH", "192.168.1.1");
System.out.print("From var: "); System.out.println(addr);//
System.out.print("Hardcoded: "); System.out.println("ADDR_PLACEH");
System.out.print("Substring: "); System.out.println("ADDR_PLACE" + "H".substring(0));
System.out.print("Equals test: "); System.out.println("ADDR_PLACEH".equals("192.168.1.1"));
System.out.print("Equals test with substring: "); System.out.println(("ADDR_PLACE" + "H".substring(0)).equals("192.168.1.1"));
Output:
Initial: ADDR_PLACEH
From var: 192.168.1.1
Hardcoded: 192.168.1.1
Substring: ADDR_PLACEH
Equals test: true
Equals test with substring: false
The result of the first Equals test is weird, isn't it? You can't expect your fellow programmers to figure out why is Java thinking they are equal...
Full test code: http://pastebin.com/vbstfWX1
Do you use StringUtils.EMPTY instead of ""?
I mean either as a return value or if you set a the value of a String variable. I don't mean for comparison, because there we use StringUtils.isEmpty()
Of course not.
Do you really think "" is not clear enough ?
Constants have essentially 3 use cases:
Document the meaning of a value (with constant name + javadoc)
Synchronize clients on a common value.
Provide a shortcut to a special value to avoid some init costs
None apply here.
I use StringUtils.EMPTY, for hiding the literal and also to express that return StringUtils.EMPTY was fully expected and there should return an empty string, "" can lead to the assumption that "" can be easily changed into something else and that this was maybe only a mistake. I think the EMPTY is more expressive.
No, just use "".
The literal "" is clear as crystal. There is no misunderstanding as to what was meant. I wouldn't know why you would need a class constant for that. I can only assume that this constant is used throughout the package containing StringUtils instead of "". That doesn't mean you should use it, though.
If there's a rock on the sidewalk, you don't have to throw it.
I'm amazed at how many people are happy to blindly assume that "" is indeed an empty string, and doesn't (accidentally?) contain any of Unicode's wonderful invisible and non-spacing characters. For the love of all that is good and decent, use EMPTY whenever you can.
I will add my two cents here because I don't see anybody talking about String interning and Class initialization:
All String literals in Java sources are interned, making any "" and StringUtils.EMPTY the same object
Using StringUtils.EMPTY can initialize StringUtils class, as it accesses its static member EMPTY only if it is not declared final (the JLS is specific on that point). However, org.apache.commons.lang3.StringUtils.EMPTY is final, so it won't initialize the class.
See a related answer on String interning and on Class initialization, referring to the JLS 12.4.1.
I don't really like to use it, as return ""; is shorter than return StringUtils.EMPTY.
However, one false advantage of using it is that if you type return " "; instead of return "";, you may encounter different behavior (regarding if you test correctly an empty String or not).
If your class doesn't use anything else from commons then it'd be a pity to have this dependency just for this magic value.
The designer of the StringUtils makes heavy use of this constant, and it's the right thing to do, but that doesn't mean that you should use it as well.
I find StringUtils.EMPTY useful in some cases for legibility. Particularly with:
Ternary operator eg.
item.getId() != null ? item.getId() : StringUtils.EMPTY;
Returning empty String from a method, to confirm that yes I really wanted to do that.
Also by using a constant, a reference to StringUtils.EMPTY is created. Otherwise if you try to instantiate the String literal "" each time the JVM will have to check if it exists in the String pool already (which it likely will, so no extra instance creation overhead). Surely using StringUtils.EMPTY avoids the need to check the String pool?
No, because I have more to write. And an empty String is plattform independent empty (in Java).
File.separator is better than "/" or "\".
But do as you like. You can't get an typo like return " ";
Honestly, I don't see much use of either. If you want to compare egainst an empty string, just use StringUtils.isNotEmpty(..)
I am recommending to use this constant as one of the building stones of a robust code, to lower the risk of accidently have nonvisible characters sneak in when assigning an empty string to a variable.
If you have people from all around the world in your team and maybe some of them not so experienced, then it might be a good idea to insist on using this constant in the code.
There are lots of different languages around and people are using their own local alphabet settings on their computers. Sometimes they just forget to switch back when coding and after they switch and delete with backspace, then text editor can leave some junk inside of "". Using StringUtils.EMPTY just eliminate that risk.
However, this does not have any significant impact on the performance of the code, nor on the code readability. Also it does not resolve some fundamental problem you might experience, so it is totally up to your good judgement weather you will use this constant or not.
Yes, it makes sense.
It might not be the only way to go but I can see very little in the way of saying this "doesn't make sense".
In my opinion:
It stands out more than "".
It explains that you meant empty, and that blank will likely not do.
It will still require changing everywhere if you don't define your own variable and use it in multiple places.
If you don't allow free string literals in code then this helps.