I am writing a method that processes a string (to extract something):
public static String myProcessor (String myInput) {...
I want to have some String object inside this method, that I can apply my transformations on (workString = workString.replace(...
)
However, I don't want to change the original string (via the reference given to my method, i.e.:
myProcessor(originalString)
) - because there may be method calls after my method has been called, which also want to process/extract something from the original string, before my method call
I am still learning Java and, according to my book (Deitel & Deitel - "Java How To Program"):
~"primitive types are pass-by-value. Other variable types are for objects and those are pass-by-reference and therefore variable assignment of an object is passing the reference to the same object. A change in the object referenced by one variable can be seen when reading the other variable (if Object var2 = var1
)"
(This isn't verbatim, just what I understood from it!)
So, I thought I'd try: String workString = new String(myInput);
and this should create a new String object, using data from myInput
, but I could manipulate workString
anyway I want, without worrying I am making changes to an object which is used elsewhere.
IntelliJ suggested that this is redundant, and I can just do: String workString = myInput
, which got me confused...
Is IntelliJ right here?
Actually, do I even need to create a local-scope workString
, or references are "detached" once a variable "arrives" into a method? (i.e.: inside myProcessor
, myInput
is no longer holding a reference to the originalString
from the call for myProcessor
, but it creates a new String object?
Could you also please mention briefly if your answer is regarding just String objects or all objects?
I have a feeling that perhaps String is somewhere between a Primitive type and an Object type and has special rules applied to it...
As mentionned by @AndyTurner,
In Java String
is immutable which means any operation on a String
doesn't change the original String
.
For instance:
myString = "Hello World"; // literal
myString = myString.replace("o", "-"); // not literal
myString = myString + " !"; // not literal
Hello World
is placed in the String Pool and assigned to variable myString
.
Hell- W-rld
is placed in the String Pool and assigned to variable myString
.
Hell- W-rld !
is placed in the String Pool and assigned to variable myString
.
BUT !
As Hell- W-rld
and Hell- W-rld !
are not literal (GC of String literals) and no more reachable, they are candidate for Garbage Collection.
In the end only two String
will be in the pool: Hello World
and !
(the two literals).
EDIT: "o" and "-" will stay in the pool as they are literals too
Could you also please mention briefly if your answer is regarding just String objects or all objects
It depends of the property,
String is not a Primitive but is treated in some regards like one. Primitives are immutable and so are String
s.
To answer your title :
Is “new String(oldString)” necessary? (Is String a reference or a value?)
It allows to store the value in the String Pool but :
String s1 = "Hi";
String s2 = new String(s1); // Any other operation would assign a new reference as String is immutable
s1 == s2; // false
s1.equals(s2); // true
A String
is passed by reference and new
assign a new reference (to a same String
in the pool). Both references are different (s1
and s2
) but both points to the same value.