4 ms·
In java + operator on strings works like this: Object a = null; String s = "foo bar " + a; // s == "foo bar null" So, it's possible to get "null" as a
by ajuc 9y ago
In java + operator on strings works like this:
Object a = null;
String s = "foo bar " + a; // s == "foo bar null"
So, it's possible to get "null" as a string downstream, when some variable that should be non-nulleable - was null. If you find such a bug and incompetently fix it by checking for "null" downstream instead of checking before turning variables into strings - you have the error from the article. Especially if you check ignoring the case.
BTW guess how I know it's working like that :)
- incongruity 9y agoSure – that's just casting a null type as a string. So I guess if you have a comparison that somehow casts null to a string before comparing, you could run into this issue, but that's still bad programming. I used to own null@myundergrad.edu as an email alias (with my real university, not that generic .edu, of course) and I got all sorts of interesting things... but that was very intentional on my part.
- monsieurbanana 9y agoI don't think anyone ever argued that this wasn't because of bad programming.
- ajuc 9y agoFunnily enough - it's not the null-> String conversion, it's the "+" operator. That was at one point subject of heated debate in my previous job :) See: "null".equals((String)null) //false "null".equals((String)null+"") //true System.out.print((String)null) // throws NPE System.out.println((String)null) // prints "null", I guess because it appends "\n" inside
- incongruity 9y agoRight, but that operator is implicitly casting the null object to a string type – it has to, in a strict sense... some other languages would raise an error (and many would do the same as Java).
- ajuc 9y agoIt doesn't have to. null.toString() throws NPE as it should. I would expect "foo" + null to throw NPE as well. BTW there's another "fun" gotcha, when you interface java code and oracle database which consider empty string and null to be the same thing. Depending on how you handle data from database you end up with null, "", or "null" :)
- Asooka 9y agoString.valueOf(null) returns "null" though, and that is what "foo" + null uses. I can understand why it would be surprising if you thought it used .toString, but it's clearly listed in the standard.
- LukeShu 9y agoSure, but .toString() can be used to change how your class stringifies, so clearly it is being called at some point (perhaps by String.valueOf()). And indeed, public static String valueOf(Object obj) { return (obj == null) ? "null" : obj.toString(); } http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/String.java#l2969 http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/s...
- incongruity 9y agoInteresting – I haven't touched Java in years so I'm definitely out of my element with that language, so thank you.
- amenghra 9y agoSystem.out.print((String)null) Does not throw NPE.
- ajuc 9y agoit does here: http://www.javarepl.com/term.html http://www.javarepl.com/term.html But you're right, in regular java environment it doesn't now that I've checked.
- ufmace 9y agoThat's insane. I've known Java to be a bit verbose, but I thought it was mostly a reasonable language aside from that. I might have expected something like that from Javascript or PHP. Never in my wildest dreams would I have thought that boring old Java would interpret a null cast to a string as a literal string "null" when combining strings. Even Ruby and Python don't do that - they throw type mismatch errors instead. C# treats it as empty string.
- DSMan195276 9y agoEhh, I don't really think this is a huge deal personally. Keep in mind that it is not that `(string)null` gives you the "null" string, or `((string)null).ToString()` gives you the null string. You have to use actual string concatenation to get it (Or as others have pointed out, `String.ToValue(null)`). Point being, it isn't/shouldn't be messing up your regular comparisons (Unless you turn it into a string beforehand), and you really shouldn't be checking for stuff like `null` against a string literal anyway - it's meant for displaying a human readable string, not an unambiguous string that could be converted back at a later time. If you wanted that then you should use proper serialization techniques rather then just concatenating a bunch of values.
- Zak 9y agoIt's insane in that Java pretends to have strong, static typing, then does things like that.
- Spivak 9y agoOverloading the plus operator for strings was probably a mistake in the language but that's hardly a condemnation of their type system.
- Zak 9y agoA lot of languages overload + to mean concatenate. I think that's a mistake, however... In Python: "abc" + None TypeError: cannot concatenate 'str' and 'NoneType' objects "abc".join(None) TypeError: can only join an iterable In Ruby "abc" + nil TypeError: no implicit conversion of nil into String In Lua = "abc" .. Nil attempt to concatenate global 'Nil' (a nil value) But not Java. Java implicitly tries to coerce the provided value to be a string, which seems out of place in a language that values type safety. That all types might also be null also seems out of place in a language with strong, static typing, but that's been discussed to death. The problem is compounded by the fact that null is actually converted to "null" instead of an empty string.
- rootlocus 9y ago> it's possible to get "null" as a string downstream I don't see the problem with that. Strings that contain formatted variables should be used for display only. Besides, when someone inputs his name, the input is already a string, and I don't see how you would dereference string contents.
- amptorn 9y agoThat's not the problem. Strings saying "null" are not the problem. That's just four lower-case characters. No system chokes on that directly. The problem is downstream, where some galactic idiot has special-cased the string "null" to turn back into an actual `null`.
- tim333 9y agoTrying it in the console just now I see javascript does it too >"hey "+null "hey null" I wonder why the language designers thought that was a good idea?
- kpil 9y agoThe reason is that the string concatenation operation is doing a String.valueOf() on the argument, and that delegates to toString() that promises a human readable string that is relevant. For some reason someone decided to check for null instead of the stricter option of throwing a NullPointerException. Maybe to help debugging or to follow the gist of toString(). I guess it was too late to change even in Java 0.9... Autoboxing, iterators and other newer features are more strict,so I suppose it's just one of the few irregularities left from prehistoric times...