I'm a C++ guy learning Java. I'm reading Effective Java and something confused me. It says never to write code like this:
String s = new String("silly");
Because it creates unnecessary String
objects. But instead it should be written like this:
String s = "No longer silly";
Ok fine so far...However, given this class:
public final class CaseInsensitiveString {
private String s;
public CaseInsensitiveString(String s) {
if (s == null) {
throw new NullPointerException();
}
this.s = s;
}
:
:
}
CaseInsensitiveString cis = new CaseInsensitiveString("Polish");
String s = "polish";
Why is the first statement ok? Shouldn't it be
CaseInsensitiveString cis = "Polish";
How do I make
CaseInsensitiveString
behave likeString
so the above statement is OK (with and without extendingString
)? What is it about String that makes it OK to just be able to pass it a literal like that? From my understanding there is no "copy constructor" concept in Java?
If I understood it correctly, your question means why we cannot create an object by directly assigning it a value, lets not restrict it to a Wrapper of String class in java.
To answer that I would just say, purely Object Oriented Programming languages have some constructs and it says, that all the literals when written alone can be directly transformed into an object of the given type.
That precisely means, if the interpreter sees 3 it will be converted into an Integer object because integer is the type defined for such literals.
If the interpreter sees any thing in single quotes like 'a' it will directly create an object of type character, you do not need to specify it as the language defines the default object of type character for it.
Similarly if the interpreter sees something in "" it will be considered as an object of its default type i.e. string. This is some native code working in the background.
Thanks to MIT video lecture course 6.00 where I got the hint for this answer.
The best way to answer your question would be to make you familiar with the "String constant pool". In java string objects are immutable (i.e their values cannot be changed once they are initialized), so when editing a string object you end up creating a new edited string object wherease the old object just floats around in a special memory ares called the "string constant pool". creating a new string object by
will only create a string object in the pool and the reference s will refer to it, but by using
you create two string objects: one in the pool and the other in the heap. the reference will refer to the object in the heap.
when they say to write
instead of
they mean it when creating a String object because both of the above statements create a String object but the new String() version creates two String objects: one in heap and the other in string constant pool. Hence using more memory.
But when you write
you are not creating a String instead you are creating an object of class CaseInsensitiveString. Hence you need to use the new operator.
Java creates a String object for each string literal you use in your code. Any time
""
is used, it is the same as callingnew String()
.Strings are complex data that just "act" like primitive data. String literals are actually objects even though we pretend they're primitive literals, like
6, 6.0, 'c',
etc. So the String "literal""text"
returns a new String object with valuechar[] value = {'t','e','x','t}
. Therefore, callingis actually akin to calling
Hopefully from here, you can see why your textbook considers this redundant.
For reference, here is the implementation of String: http://www.docjar.com/html/api/java/lang/String.java.html
It's a fun read and might inspire some insight. It's also great for beginners to read and try to understand, as the code demonstrates very professional and convention-compliant code.
Another good reference is the Java tutorial on Strings: http://docs.oracle.com/javase/tutorial/java/data/strings.html
It is a basic law that Strings in java are immutable and case sensitive.
String
s are special in Java - they're immutable, and string constants are automatically turned intoString
objects.There's no way for your
SomeStringClass cis = "value"
example to apply to any other class.Nor can you extend
String
, because it's declared asfinal
, meaning no sub-classing is allowed.