views:

302

answers:

10

Why is java.lang.String the only class for which two ways of creation exist:

1) With normal way with "new" keyword.

String s = new String("abc");

2) With String literal (which is only available with String class)

String s = "abc";

So why are there String literals and no literals for any other classes??

+10  A: 

Short answer, because the language designers felt like it.

I guess String is such a common class that they made an exception. I'm sure there's a few other similar exceptions as well, (see Tom Hawtins comment)

Glen
Operator overloading for strings (the + operator) strikes me as a related exception
Brian Agnew
A: 

Last I checked:

Integer wInt = 1;

Works just fine.

Peter D
I think this is because of the auto-boxing feature introduced in Java 5.0, and would not work on previous versions.
pgb
5.0 is five years old now!
Tom Hawtin - tackline
Time flies when you're coding in Java!
Jay
+1  A: 

String, while being an ordinary class, represents one of the basic elements of programming (the others being numbers and boolean values). Therefore, Java has considered String objects as semi-primitive variables from day one, and allowed this.

Later on, when auto-boxing became part of the standard compiler, you could also build numeric wrapper objects in this way, i.e.

Integer i = 123;

as Tom Hawtin-tackline mentions in the comments to the question.

Yuval
+5  A: 

Leaving aside autoboxing (which doesn't count IMO - the literals are for the primitive types rather than the classes; there's just an implicit conversion to the wrapper class), the String(String) constructor is actually useful. It takes a copy of the character data, which means that if the original string is small but with a large backing char[], the new string is independent of it.

This can be important if you're reading short lines from a file, for example.

As for why there are string literals: because they're useful. What would you have instead? Would you want to force developers to use:

String x = new String(new char[] { 'h', 'e', 'l', 'l', 'o' });

and at the same time not get interning?

What other class would you want a literal for? Arguably literals for maps and lists would be useful - I can't remember whether they're coming in Java 7 or not. You can think of array initializers as "a bit like a literal" in that it's a shorthand for object initialization.

Jon Skeet
+1: just what I thought... maybe we should have string primitives: string prim = "abc"; String boxed = new String(prim); or not have primitives at all :-)
Carlos Heuberger
Decimal and BigInteger.
Jason Orendorff
+2  A: 

I suppose because String is such as fundamental data type that they regard it at the same level as primitives.

Btw,

new String("abc");

actually creates 2 Strings:

  1. the interned one, of which you lose the reference
  2. a new instance with the same content

Personally, I've never find a need to use String's constructor.

RichN
+1 for being the only answer to mention this.
Kevin Panko
A: 

The latter form of creation also involves String interning. That is, if you have the code:

String s = "abc";
String t = "abc";

the compiler will optimize this and you get two references to the same String object. (s == t will be true).

String interning works for string expressions too.

+1  A: 

The object types which have literals are Strings, null and class literals.

It's also possible to use initialisers for arrays and primitive literals can also be used to create objects if used as initialisers, which fit the "two ways of creation" in simple syntax without being true literals ( they can only be used to initialise a value rather than in all places that an object expression can occur ).

If you use other techniques such as serialisation and reflection, you can break the "two ways of creation" too.

Pete Kirkham
You also have literals for Class objects.
Michael Borgwardt
True. Was looking at the lexical level.
Pete Kirkham
A: 

There are, of course, also literals for all the primitive numeric types, and the booleans true and false, and chars. I suppose you could reply that in your question you technically said "no literals for any other classes". Okay. I think someone pointed out that "null" is a literal Object, so your statement is technically inaccurate, but I think that's the only other example.

But then, the next obvious question is, what other classes would you want to have literals for? If you were designing the language, what would a BufferedReader literal look like? Or a ResultSet literal? Or a JCheckBox?

You could theoretically say that, for example, a "File literal" is the file name enclosed in some special delimiter, like "$/home/bob/myfile.txt$". But then someone could say, What about a JButton, couldn't we make a literal for that like with the text of the button and the ActionListener it fires and appropriate delimiters, like "%Submit,SubmitListener%". And then what about Sockets, couldn't we put the host name in some special delimiter, etc. I think it's pretty clear we'd quickly run out of punctuation marks to use as delimiters. So we'd end up having to write some sort of text to identify which class we're talking about, like saying File("/home/bob/myfile.txt") or Socket("www.example.com",631). But that looks an awful lot like a constructor, and we'd be right back to what the authors of Java actually did.

The number of "things" that can be expressed purely by the nature of the value (e.g. all digits make a numeric literal) or with punctuation is pretty limited by the number of punctuation marks that can be reaonably fit on a keyboard. And would you want a keyboard with 600 special icons for all the different sort of things you might want to talk about? Words are so much easier and more flexible.

String is so commonly used, and alternatives would have been so awkward, that it made sense to make it a special case.

Jay
A: 

String literals are a convenient short cut with a well established precedence (in C) and syntax. If the Java designers wanted to lure C++ programmers over, the string literals had to be there. Fortunately the string handling is much saner in Java than in C++.

No other standard objects had a de facto syntax - how would you write a map literal?

Thorbjørn Ravn Andersen
It rather depends on your definition of sane. C++ has UTF-16 strings just like Java, but unlike Java integrate fully into the iteration and array access idioms ( you can't do a for(:) on a String in Java, but you can std::foreach on a std::string in C++ ) and ( if you include boost ) similar regex support that Java has.
Pete Kirkham
"how would you write a map literal?" Python has map literals. JavaScript has object literals and array literals. They're useful.
Jason Orendorff
+1  A: 

Java 7 is slated to provide the ability to initial collections via literals much like the array literals:

Matt