17

Why didn't Java designers create static versions of string manipulation methods in the java.lang.String class? The following methods are what I refer to, but the question can be extended to other non-static methods in the class as well.

concat(String)                        substring(int, int)
replace(char, char)                   toLowerCase()
replace(CharSequence, CharSequence)   toLowerCase(Locale)
replaceAll(String, String)            toString()
replaceFirst(String, String)          toUpperCase()
split(String)                         toUpperCase(Locale)
split(String, int)                    trim()
substring(int)

Having only non-static versions of these methods forces explicit null-checking anywhere such a method has to be called. For example, simply calling example = example.trim() would lead to NullPointerException if String example = null. So the programmer has to do the following boilerplate null check:

if (example != null)
    example = example.trim();
// OR:
example = (example==null) ? null : example.trim();
example = (example==null) ? null : example.substring(5);

I would imagine it would have been a lot more convenient if String had static versions of these methods (perhaps even exclusively), which would take the input string as the first argument:

example = String.trim(example);
example = String.replace(example, 'a', 'b');
example = String.substring(example, 5);

This would have led to cleaner code written by programmers which would have automatically taken care of null cases by simply returning null, rather than forcing programmers to explicitly handle null cases. The returning of null makes sense to me since manipulating a null string should result in a null string, not an error.

Why didn't Java designers think of this when they designed the String class in Java 1 or Java 2, or even add such a functionality in a later Java version?

17
  • 17
    I would suggest replacing "Why didn't Java designers think of X" with "Why did Java designers decide against X". Give them the basic credit of not being blind to the option. Commented Dec 12, 2013 at 8:06
  • 5
    null is an exceptional state and should be handled explicitly. Commented Dec 12, 2013 at 8:56
  • 2
    @KonradMorawski: Personally I find that a gross misuse of extension methods. If you have a null value then what on earth are you doing trying to call methods on it, you're just going to confuse everyone who reads that code. It's a poor reimplementation of a Maybe<T> type, I guess?
    – Phoshi
    Commented Dec 12, 2013 at 9:29
  • 2
    @Phoshi one has to keep in mind that extension methods are NOT real methods, they're just syntax sugar. But I agree that it's controversial. I wish C# / Java offered some sort of built-in syntactic null-safety, like - say - Kotlin. string name = employee?.personalData?.name. Just as a shortcut for all these repetitive if (employee != null)s. Related SO question: stackoverflow.com/questions/1196031/… Commented Dec 12, 2013 at 9:39
  • 2
    @ADTC Erm, you do realize that a program can't predict in advance that a value is null, right? - You should define the contracts between your interfaces in a way that you can be sure if a value is allowed to be null or not. Null-checking everywhere means you have a program design issue.
    – Uooo
    Commented Dec 12, 2013 at 12:17

4 Answers 4

30

The returning of null makes sense to me since manipulating a null string should result in a null string, not an error

Well, that is your opinion. Others may argument that String operations on a null object, which does not contain a String, make no sense and hence should throw an Exception

Why "Java designers" did or did not something is difficult to anwer.

There are already libraries out there which can do null-safe String operations, e.g. StringUtils of Apache Commons. You can use that or similar libraries if you need them.


Addition based on your comments

Reading through the comments, it seems like the real problem you face is that you have to check for null all over your code. That can be an indicator of a bad program design without clearly defined contracts between interfaces. You might want to read Avoiding “!= null” statements in Java?

3
  • 1
    Thanks for your feedback. I guess the real question is, why do we have to depend on an external library or home-brewed classes when such a basic feature can be made part of standard Java?
    – ADTC
    Commented Dec 12, 2013 at 8:02
  • 4
    @ADTC let's put the question the other way round: Why should "Java designers" include something into the language, if there are already lots of good libraries out there, well tested and documented? How to define a "basic feature" is opinion based. Doesn't mostly every project need some external library for "Basic functionality" (unit testing, mocking, date and time,...)? It ain't a big deal, is it?
    – Uooo
    Commented Dec 12, 2013 at 8:13
  • One way of dealing with nulls is using Guava's Optional - code.google.com/p/guava-libraries/wiki/… Commented Dec 12, 2013 at 12:32
10

IMO the whole "if arg is null return null" approach to writing methods needlessly increases the cyclomatic complexity of your program.

Early Java libs used the return null approach, but the JDK guys always guarded against null with exceptions.

With time, I think the latter approach has come out as the clear winner.

Why? Since null fields break a lot of oo principles. You simply cannot treat them as members of a polymorphic class. This means that you always have to code special cases for null, and hence your cyclomatic complexity soars when you have to assume that things can be null.

In order to solve your problems, consider using the null object pattern instead of relying on null fields.

5
  • 2
    But String is not polymorphic, no? And how do you use the null object pattern for an already existing type like String?
    – svick
    Commented Dec 12, 2013 at 9:05
  • String is not polymorphic, no. But even so you would like to know that you can call instance methods on any string reference that you have. This works for all non-null references. String already has a null object: the empty string. Just like lists have the empty list. So ask yourself why the empty string isn't enough in your case. I guess that you use a null string to flag some special case. Ask yourself if you can use a separate flag for that special case. Commented Dec 12, 2013 at 15:27
  • 1
    @AlexanderTorstling: A field of type int defaults to zero rather than null. Conceptually it should be possible to have a string type whose default value would be an empty string rather than null [such a type could semantically be to String what int is to Integer]. The fact that a non-empty string would internally hold a reference to a heap object would be an implementation detail; there's no reason it couldn't behave semantically like a primitive.
    – supercat
    Commented Dec 23, 2013 at 19:29
  • @supercat: Agreed. I think it would have been better to forbid null values for refefences unless explicitly enabled. Default non-null and final fields. Many types already have null behaviour objects Commented Dec 25, 2013 at 11:32
  • @AlexanderTorstling: Having storage locations of all types default to all-bytes-zero, and providing that structure types can be assigned via all-bytes-copy, greatly simplifies a framework, but pretty much implies that types with mutable reference semantics must default to null. It would have been helpful, however, to have had framework support for value types which would encapsulate a single reference and would "box" as--and could unbox from--that reference type.
    – supercat
    Commented Dec 25, 2013 at 19:59
3

Not saying this is the reason, but except for toString, all of these methods are easily encapsulated in a static helper class, while the reverse is not true.

I.e. if you want Stings.toUpper(string input) the code for that is easy to write, but if you want instance.toUpper and all you have is String.toUpper, well, that is impossible...unless they introduce extension methods, which most likely wasn't even considered at the time.

3
  • Good point, although more of a comment than an answer. But even given that, why do we have to depend on an external library or home-brewed classes when such a basic feature can be made part of standard Java?
    – ADTC
    Commented Dec 12, 2013 at 7:59
  • 2
    As of now, you do have String.format (static), but you can't do "something %s".format(id). Commented Dec 12, 2013 at 11:09
  • @adtc: because it's not a basic feature of the language to do it via a static class. Starting from that premise, there's a lot of reasons not to do so - unnecessary code/code bloat, duplicate functionality, cost of development/maintenance.
    – jmoreno
    Commented Dec 12, 2013 at 16:25
-2

In java, that string is an object. That's a design choice.

Object references can be null and are null if there is no object assigned to it. If you call such an object, a NullPointerException is thrown. That's standard oo-behaviour.

Java designers made the choice of having strings as object and having those methods throwing null-pointer exceptions is what you get if you want strings to be objects.

Why didn't Java designers think of this when they designed the String class in Java 1 or Java 2, or even add such a functionality in a later Java version?

They probably did think about it and chose to incorporate oo-behaviour.

4
  • May I know, how is creating static methods to take care of null cases not OO behavior? To be clear, I'm not saying it is, but I'm trying to understand why you say the design decision is to incorporate OO behavior.
    – ADTC
    Commented Dec 12, 2013 at 9:40
  • Static methods are more like functions. And for the use you want they shouldn't even be part of the string class rather be part of some utility class. Just like math class functions.
    – Pieter B
    Commented Dec 12, 2013 at 9:58
  • 4
    Just because strings are objects doesn't mean that the String class can't have static methods. And indeed it has some already, eg. String.format. (Same in C#, by the way). So if that's a design choice, it can't come solely from the fact that strings are objects, and it's not applied consistently. Commented Dec 12, 2013 at 11:04
  • @PieterB I wouldn't complain if at least such methods were provided in a Strings utility class, like we have Arrays utility class (although I understand it was created out of sheer necessity due to arrays being some sort of a weird cross between primitives and objects :)).. as long as it was part of standard Java and didn't require dependencies.
    – ADTC
    Commented Dec 14, 2013 at 7:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.