String.Empty Field

Requesting built-in read only representation of the empty string similler to C# .NET has on MSDN
for example:

public class String /* some code */ {
    companion object {
        @JvmField
        public val Empty: String = ""
    }
}

Uses:

String.Empty
4 Likes

I never understood the reason behind String.Empty and I’ve always refused to use it.
Some people tell me it’s more readable, which is something I completely disagree with. It’s like saying Math.plus(1, 3) is more readable than 1 + 3.

7 Likes

Why do you need it? Just use "". It’s like asking for Integer.ZERO constant.

6 Likes

0 is zero itself but “” are not empty string itself but opening and closing quotes. In my opinion just two quotes as, for example, a function argument look a bit ugly, and it’s a case when unnamed constant should be taken out as a property.
Of course, it’s a matter of taste, so why not to provide the choice to developers. Or at least to provide more usecases and explanations showing one variant is truly worse than another.

1 Like

The developers have the choice of declaring this constant in their own code if they find this more readable. No reason why this needs to be in the standard library.

7 Likes

I think Microsoft did it for the same reasons we have an Integer cache in the Integer class and there is the static constant Boolean.TRUE, that is for performance. There can be many empty String instances in a program if you don’t have String.EMPTY.

1 Like

While it’s true that there can be many instances of empty string in a program, those empty strings that come from literal "" are usually interned by JVM. Therefore both String.EMPTY constant and any constant denoted by "" literal will be represented with the same empty string instance at run time.

6 Likes

In C# (and .NET generally), string literals are always interned to avoid duplication and so there can never be more than one instance of “”. If you look at the code for String.Empty it actual refers to “” in the background so, like @ilogico, I could never understand the reason why some people insisted on using String.Empty instead.

Similarly, in Kotlin, I can’t really see why:

if (s.isEmpty()) ....

is often considered superior to the more direct:

if (s == "") ...

1 Like

(Side note: I was under the impression these were always interned. Maybe there’s an exception for strings of unusual size, though.)

2 Likes

For me, I think it’s more about making your intention clear.

If you use "" how do we know you didn’t typo the magic string value? String.Empty is very explicit about what you’re trying to do.

e.g.

return new someKindOfObject(myResult1, "");

vs.

return new someKindOfObject(myResult1, String.Empty);

2 Likes

I should add as part of the example:

return new someKindOfObject(myResult1, " ");
return new someKindOfObject(myResult1, "''");
return new someKindOfObject(myResult1, "something was supposed to be here");

1 Like

Defining a string literal will usually result in the same String object as @ilya.gorbunov points out, however when creating new strings consider the following Java code:

String empty = "";
String alsoEmpty = "";
System.out.println(empty == alsoEmpty);
System.out.println(empty == new String(alsoEmpty));
System.out.println(empty == new StringBuilder().toString());
System.out.println(empty == new String());
System.out.println(empty == new String(new char[0]));

The result is true, false, false, false, false.

To me the nicety of Kotlins isEmpty() is the intent is obvious and, as @peteski points out a lot less likely to confuse "" with " ". Also worth noting that the implementation of isEmpty() shows it checks the length, which is considered faster than comparing to an empty string.

Your example is not that relevant though, because == in Kotlin is equivalent to javas isEquals method and as far as I can tell no one checks string equality using ===. That being said, I like isEmpty() as it shows the intent.

Is String merging an issue in Kotlin?

Still no comments on string merging? The question is still valid in my mind. Using a literal 0 as similar to “” is not valid to my mind. A “” may be stored in the app’s static data section and have a pointer to it while a literal 0 may be part of a CPU instruction set, so they are very different internally. If the language makes a promise to merge, then I’m good. However without that promise, I’m okay in that I can define my own constant if I want merging, but I have to do the work to make that happen. Can I get an answer please?

Here’s a case I’ve just got.

data class Person(val firstName: String, val middleName: String? = null, val lastName: String) {
    val fullName: String = "$firstName $middleName $lastName"
}

Here’s what I’m getting if middle name is NULL

John null Doe

What I have to do now is to add an emptyString constant which I can use in this string interpolation. It would be much simpler if language would offer this already.

I need to use NULL default value here, because this is stored in database and is send over several SOAP and REST requests.

I’m not sure what your question is? How is this relevant to this topic at hand?

1 Like

That’s what writing your own code is useful for. If you seriously actually truly really do need a String.Empty for whatever reason, you can just do this

val String.Empty: String get() = ""

It does exactly what you want and that’s the purpose of these types of things.

1 Like

I’ve resolved problem with null as follow:

val fullName: String = "$firstName ${middleName ?: emptyString()} $lastName"

My point is that I have to define emtpyString() myself and I would prefer to have it defined in the language.

I did exactly that, though I defined emptyString() function, but…
Kotlin have emptyList(), emptyMap() etc, why not have emptyString() or something similar. For me that would be consistent and convenient.