Java is a 'pass by value' language, meaning that sending in a variable into a method, pointing the variable to a new object, does not effect the outer variable.
public void one() {
String s = "one";
two(s);
System.out.println(s);
}
public void two( String s ) {
s = "two";
}
Would write "one".
Is there a way to prevent this? Or what is the most common solution or pattern to actually change s to "two" inside the method?
Is not possible to prevent it.
You can emulate it with a generic wrapper like this:
class _<T>{
public T _;
public _(T t ) {
_ = t;
}
public String toString(){ return _.toString(); }
}
And then use it as you intended.
class GeneriWrapperDemo {
public static void main(String [] args ) {
_<String> one = new _<String>("One");
two( one );
System.out.println( one );
}
public static void two( _<String> s ) {
s._ = "two";
}
}
But looks ugly. I think the best would be to change the reference it self:
public String two( String a ) {
return "two";
}
And use it
String one = "one";
one = two( one );
:)
You can't pass-by-reference - at least not the variable itself. All parameters are passed by value. However, objects contain references - and are represented as references themselves. You can always change the insides of the object, and have the changes stick. Thus, send an array, or create a wrapper class, or make your own reference object:
class Ref<T> {
T obj;
public Ref(T value) {
this.obj = value;
}
public void set(T value) {
obj = value;
}
public T get() {
return obj;
}
}
As the others have said, String is not mutable anyway, so you're not actually changing the string here, but making the variable point the other way, so it does not really make that much sense not to simply return the new string.
If s were a mutable object, you could change its value (i.e. the value of its data members). And the member can be a String too. This doesn't work with a String parameter directly, as it is immutable, so the only way to "change" it is to direct the reference to a different object.
Create an object, which contains the string, then pass that into the method.
public class StringHolder {
public String s;
public StringHolder(String s) {
this.s = s;
}
}
Then the code would look like:
public void two(StringHolder sh) {
sh.s = "two";
}
StringHolder sh = new StringHolder("one");
two(sh);
System.out.println(sh.s);
Although, for the above example, you could just return the value you want:
public String two(String s) {
return "two";
}
String s = "one";
s = two(s);
System.out.println(s);
And for Strings, you can always use StringBuffer, which is mutable:
public void two(StringBuffer buf) {
buf.setLength(0);
buf.append("two");
}
You can't prevent Java from passing by value; that's the language semantics.
You can, one way or another, get around it, depending on what you want to do.
You can return a new value based on the parameter that's passed:
static String scramble(String s) {
return s.replaceAll("(.*) (.*)", "$2, $1");
}
// then later...
String s = "james bond";
s = scramble(s);
System.out.println(s); // prints "bond, james"
You can also pass something that is mutable:
static void scramble(StringBuilder sb) {
int p = sb.indexOf(" ");
sb.append(", ").append(sb.substring(0, p)).delete(0, p+1);
}
// then later...
StringBuilder sb = new StringBuilder("james bond");
scramble(sb);
System.out.println(sb); // prints "bond, james"
Strings are immutable... otherwise, though, all you would have to do is call a method to operate on the same object and have that somehow change the string value.
I'm sure there are a number of Java classes that will do the job for you, but you could also roll your own simply by creating an encapsulating class with either a public field or a setter/getter. An example of the former is something like this:
public class EncapsulatedString
{
public String str;
public EncapsulatedString(String s)
{
str = s;
}
}
Create a wrapper that contains your object and change contents of the wrapper:
public class StringWrapper {
private String str;
public String getString() {
return str;
}
public String setString(String str){
this.str = str;
}
public String toString() {
return str;
}
}
public void one() {
StringWrapper s = new StringWrapper();
s.setString("one");
two(w);
// This will print "two"
System.out.println(s);
}
public void two( StringWrapper s ) {
s.setString("two");
}
One ugly solution that comes to my mind is to pass around a String array of length 1. It's not something I would encourage but if you feel that you want to do it...
1 public class One {
2
3 public static void main( String[] _ ) {
4 String[] s = {"one"};
5 two(s);
6 System.out.println(s[0]);
7 }
8
9 public static void two( String[] s ) {
10 s[0] = "two";
11 }
12 }
1-length array is a bit ugly, but perfectly working solution. No need to create surplus wrapper classes:
public void one() {
String[] s = new String[]{"one"};
two(s);
System.out.println(s[0]);
}
public void two(String[] s) {
s[0] = "two";
}
This pattern is especially useful when translating old (e.g. C) code where pass by reference has been extensively applied.
That said, returning a new, fresh value is always less confusing than mutating the "input" value.
Use StringBuffer, or StringBuilder, which are mutable.
Java is not a pass-by-value language. On the contrary - it is a pass-by-reference language. (passing-by-reference does not mean you can change the original "pointer" to point elsewhere like C++ allows).
The only things which are passed by value are primitives (int, long, char etc.)
Object references are always passed by reference - so if your Object is able to support change to its contents (e.g. via getter and setter methods) - it can be changed.
String specifically is immutable - meaning that its contents may never be changed. So for your specific question, if you want the String referred to by the local variable 's' to change you need to provide it with a reference to a new instance of a String object.
Example:
public void one()
{
String s = "one";
s = two(); // Here your local variable will point to a new instance of a String with the value "two"
System.out.println(s);
}
public String two()
{
return "two";
}
If you use objects other than String - you can define setter methods on them that will update their contents for you.
Related
Consider the following Java program:
Version 1:
public class Traverse
{
public static void main(String[] args)
{
String str = "Frog";
// processString(str);
str = str.substring(2, 3) + str.substring(1, 2) + str.substring(0, 1);
System.out.println(str);
}
}
Version 2:
public class Traverse
{
public static void main(String[] args)
{
String str = "Frog";
processString(str);
System.out.println(str);
}
public static void processString (String str)
{
str = str.substring(2, 3) + str.substring(1, 2) + str.substring(0, 1);
}
}
Version 1 prints the output "orF", while version 2 prints the output "Frog".
It seems that when we attempt to use the processString method (version 2) to change the string, it fails, while if we try to manually change the string without using the processString method (version 1), it succeeds.
Why is this the case?
Strings are Reference/Complex Object Type. And every reference type in java is a subclass of type java.lang.object
this means a String variable holds a reference to the actual data. However, a copy of the reference is passed. (In Java nothing is passed by reference) Object references are also passed by value. Next to that String class is immutable, meaning when you create a String object an array of characters is made; when this is "edited" its not actually getting edited, but a new object is being made from the contents of the old string + the edits you have done.
these two together result in the string "not being edited" outside the method, because the passed refrence value is changed (the refrence to the array inside the String) and when a refrence is change in a method, the original refrence doesnt change outside the method. resulting in all changes only done on the string inside the method and not outside. if you could change the array values inside the string, it technically would have changed. (but as far as i know that is not possible on the String class).
Now you have a few options to do it in a method:
by returning the changed value:
public class Traverse
{
public static void main(String[] args)
{
String str = "Frog";
str=processString(str);
System.out.println(str);
}
public static String processString (String str)
{
return str.substring(2, 3) + str.substring(1, 2) + str.substring(0, 1);
}
}
or by a holder class:
public class Holder{
public String str;
}
void fillString(Holder string){
string.str.substring(2, 3) + string.str.substring(1, 2) + string.str.substring(0, 1);
}
there are also other ways for example with an array of length 1 (depending on your usecase outside of this question).
I am trying to create an alias for a object variable in Java so that I can change one and have it affect the other. For example, in this snippet, I expect "b" to be printed out. Instead I get "a".
String s = new String("a");
String t = s;
t = new String("b");
System.out.println(s); // Prints "a".
I thought that non-primitive types in Java were able to be referenced and "tied" together like this.
No, it never works like that. Variables, fields etc. cannot be "bound" in Java.
Your variables can contain "a link to a value" in a variable, but you cannot have a "link to another variable".
This means that in your case s and t initially hold the link to the same value, but they don't know about each other. When you assign a new string to t, the value of the old string does not change (and s still references the old value). It's just the reference in `t
String is not good example, because this is immutable. You have to look at using object instances and object reference. One object instance could have multiple object references.
class Decorator {
private String str;
public Decorator(String str) {
this.str = str;
}
public void setStr(String str) {
this.str = str;
}
public String getStr() {
return str;
}
}
Decorator s = new Decorator("a"); // s - is a reference to Decorator
System.out.println(s.getStr()); // prints "a"
Decorator t = s; // t - is an another reference to existed Decorator (two references for one instance)
t.setStr("b");
// references s and t both point to one Decorator instance
System.out.println(s.getStr()); // prints "b"
System.out.println(t.getStr()); // prints "b"
You might be looking for something like this:
StringWrapper sw = new StringWrapper(new String("a"));
StringWrapper tw = sw;
tw.setS(new String("b"));
System.out.println(sw.getS()); // Prints b
class StringWrapper {
private String s;
public StringWrapper(String s) {
this.s = s;
}
private String getS() {
return s;
}
private void setS(String s) {
this.s = s;
}
}
(You can replace new StringWrapper(new String("a")) with new StringWrapper("a"). I added new String so it looks more like your example. Same goes for new String("b").)
How to return the two parameters in web method.?
I have tried these things,but the below code is returning only one parameter.
web method
public class GetTMSMargin
{
public String GetTMSMargin(String fd,String td)
{
return fd;
}
}
Can any one please mend this code and make me clear?
Thanks in advance!..
You can send array like this
public class GetTMSMargin
{
public String[] GetTMSMargin(String fd,String td)
{
//your code
String array[] = {fd, td};
return array;
}
}
You can return an array, set, map... and many other things that may contain any number of results (I prefer "result" to "parameter" as an indication of return variable).
BTW: If you are thinking about webservice here than you will need to serialise (JSON or something similar) your array/set/map...
If you want to return two values, I suggest you an ArrayList, or a table like Lucifer did.
public ArrayList <String> GetTMSMargin(String fd,String td)
{
ArrayList <String> theArray = new ArrayList <String>();
theArray.add(fd);
theArray.add(td);
return theArray;
}
You may need to read up a little more on Java. In Java a function can only return one value. If you need to return multiple values, then you will need to return either an Array of values (if they are all of the same type, a List etc count as an array for these purposes) or an Object with these values as its properties, e.g.:
class ReturnMultipleValues {
/**
* Returns an object containing the two Strings passed.
*/
public ComplexReturnValue getComplexReturnValue(String arg1, String arg2) {
ComplexReturnValue value = new ComplexReturnValue(arg1, arg2);
return value;
}
/**
* Value type which contains 2 strings
*/
public static class ComplexReturnValue {
private String arg1;
private String arg2;
public ComplexReturnValue(String arg1, String arg2) {
this.arg1 = arg1;
this.arg2 = arg2;
}
public String getArg1() {
return arg1;
}
public String getArg2() {
return arg2;
}
}
/**
* Main method just runs a quick example
*/
public static void main(String[] args) {
ReturnMultipleValues rmv = new ReturnMultipleValues();
ComplexReturnValue crv = rmv.getComplexReturnValue("Hello", "World");
crv.getArg1(); // Returns "Hello"
crv.getArg2(); // Returns "World"
}
}
Practically in any computer language you can not return more than one parameter from a function/method.
You might achieve it by returning an Array from function/method. In array you can store more than one value, so in return value you will get more than one value.
public String[] getMyValues ( String fd,String td )
{
String [] returnValues = new String { fd, td };
return returnValues;
}
As being android code you may also use another Class called ArrayList for returning multiple values.
however this is just a trick/logic to return more than one value, not a perfect solution.
This question already has answers here:
Does Java have something like C#'s ref and out keywords?
(7 answers)
Closed 1 year ago.
Could someone please give me some sample code that uses an output parameter in function? I've tried to Google it but just found it just in functions. I'd like to use this output value in another function.
The code I am developing intended to be run in Android.
Java passes by value; there's no out parameter like in C#.
You can either use return, or mutate an object passed as a reference (by value).
Related questions
Does Java have something like C#'s ref and out keywords?
? (NO!)
Is Java pass by reference? (NO!)
Code sample
public class FunctionSample {
static String fReturn() {
return "Hello!";
}
static void fArgNoWorkie(String s) {
s = "What am I doing???"; // Doesn't "work"! Java passes by value!
}
static void fMutate(StringBuilder sb) {
sb.append("Here you go!");
}
public static void main(String[] args) {
String s = null;
s = fReturn();
System.out.println(s); // prints "Hello!"
fArgNoWorkie(s);
System.out.println(s); // prints "Hello!"
StringBuilder sb = new StringBuilder();
fMutate(sb);
s = sb.toString();
System.out.println(s); // prints "Here you go!"
}
}
See also
What is meant by immutable?
StringBuilder and StringBuffer in Java
As for the code that OP needs help with, here's a typical solution of using a special value (usually null for reference types) to indicate success/failure:
Instead of:
String oPerson= null;
if (CheckAddress("5556", oPerson)) {
print(oPerson); // DOESN'T "WORK"! Java passes by value; String is immutable!
}
private boolean CheckAddress(String iAddress, String oPerson) {
// on search succeeded:
oPerson = something; // DOESN'T "WORK"!
return true;
:
// on search failed:
return false;
}
Use a String return type instead, with null to indicate failure.
String person = checkAddress("5556");
if (person != null) {
print(person);
}
private String checkAddress(String address) {
// on search succeeded:
return something;
:
// on search failed:
return null;
}
This is how java.io.BufferedReader.readLine() works, for example: it returns instanceof String (perhaps an empty string!), until it returns null to indicate end of "search".
This is not limited to a reference type return value, of course. The key is that there has to be some special value(s) that is never a valid value, and you use that value for special purposes.
Another classic example is String.indexOf: it returns -1 to indicate search failure.
Note: because Java doesn't have a concept of "input" and "output" parameters, using the i- and o- prefix (e.g. iAddress, oPerson) is unnecessary and unidiomatic.
A more general solution
If you need to return several values, usually they're related in some way (e.g. x and y coordinates of a single Point). The best solution would be to encapsulate these values together. People have used an Object[] or a List<Object>, or a generic Pair<T1,T2>, but really, your own type would be best.
For this problem, I recommend an immutable SearchResult type like this to encapsulate the boolean and String search results:
public class SearchResult {
public final String name;
public final boolean isFound;
public SearchResult(String name, boolean isFound) {
this.name = name;
this.isFound = isFound;
}
}
Then in your search function, you do the following:
private SearchResult checkAddress(String address) {
// on address search succeed
return new SearchResult(foundName, true);
:
// on address search failed
return new SearchResult(null, false);
}
And then you use it like this:
SearchResult sr = checkAddress("5556");
if (sr.isFound) {
String name = sr.name;
//...
}
If you want, you can (and probably should) make the final immutable fields non-public, and use public getters instead.
Java does not support output parameters. You can use a return value, or pass in an object as a parameter and modify the object.
You can either use:
return X. this will return only one value.
return object. will return a full object. For example your object might include X, Y, and Z values.
pass array. arrays are passed by reference. i.e. if you pass array of integers, modified the array inside the method, then the original code will see the changes.
Example on passing Array.
void methodOne{
int [] arr = {1,2,3};
methodTwo(arr);
...//print arr here
}
void methodTwo(int [] arr){
for (int i=0; i<arr.length;i++){
arr[i]+=3;
}
}
This will print out: 4,5,6.
As a workaround a generic "ObjectHolder" can be used. See code example below.
The sample output is:
name: John Doe
dob:1953-12-17
name: Jim Miller
dob:1947-04-18
so the Person parameter has been modified since it's wrapped in the Holder which is passed by value - the generic param inside is a reference where the contents can be modified - so actually a different person is returned and the original stays as is.
/**
* show work around for missing call by reference in java
*/
public class OutparamTest {
/**
* a test class to be used as parameter
*/
public static class Person {
public String name;
public String dob;
public void show() {
System.out.println("name: "+name+"\ndob:"+dob);
}
}
/**
* ObjectHolder (Generic ParameterWrapper)
*/
public static class ObjectHolder<T> {
public ObjectHolder(T param) {
this.param=param;
}
public T param;
}
/**
* ObjectHolder is substitute for missing "out" parameter
*/
public static void setPersonData(ObjectHolder<Person> personHolder,String name,String dob) {
// Holder needs to be dereferenced to get access to content
personHolder.param=new Person();
personHolder.param.name=name;
personHolder.param.dob=dob;
}
/**
* show how it works
*/
public static void main(String args[]) {
Person jim=new Person();
jim.name="Jim Miller";
jim.dob="1947-04-18";
ObjectHolder<Person> testPersonHolder=new ObjectHolder(jim);
// modify the testPersonHolder person content by actually creating and returning
// a new Person in the "out parameter"
setPersonData(testPersonHolder,"John Doe","1953-12-17");
testPersonHolder.param.show();
jim.show();
}
}
Wrap the value passed in different classes that might be helpful doing the trick, check below for more real example:
class Ref<T>{
T s;
public void set(T value){
s = value;
}
public T get(){
return s;
}
public Ref(T value) {
s = value;
}
}
class Out<T>{
T s;
public void set(T value){
s = value;
}
public T get(){
return s;
}
public Out() {
}
}
public static void doAndChangeRefs (Ref<String> str, Ref<Integer> i, Out<String> str2){
//refs passed .. set value
str.set("def");
i.set(10);
//out param passed as null .. instantiate and set
str2 = new Out<String>();
str2.set("hello world");
}
public static void main(String args[]) {
Ref<Integer> iRef = new Ref<Integer>(11);
Out<String> strOut = null;
doAndChangeRefs(new Ref<String>("test"), iRef, strOut);
System.out.println(iRef.get());
System.out.println(strOut.get());
}
This is not accurate ---> "...* pass array. arrays are passed by reference. i.e. if you pass array of integers, modified the array inside the method.
Every parameter type is passed by value in Java. Arrays are object, its object reference is passed by value.
This includes an array of primitives (int, double,..) and objects. The integer value is changed by the methodTwo() but it is still the same arr object reference, the methodTwo() cannot add an array element or delete an array element. methodTwo() cannot also, create a new array then set this new array to arr. If you really can pass an array by reference, you can replace that arr with a brand new array of integers.
Every object passed as parameter in Java is passed by value, no exceptions.
Thank you. I use passing in an object as a parameter. My Android code is below
String oPerson= null;
if (CheckAddress("5556", oPerson))
{
Toast.makeText(this,
"It's Match! " + oPerson,
Toast.LENGTH_LONG).show();
}
private boolean CheckAddress(String iAddress, String oPerson)
{
Cursor cAddress = mDbHelper.getAllContacts();
String address = "";
if (cAddress.getCount() > 0) {
cAddress.moveToFirst();
while (cAddress.isAfterLast() == false) {
address = cAddress.getString(2).toString();
oPerson = cAddress.getString(1).toString();
if(iAddress.indexOf(address) != -1)
{
Toast.makeText(this,
"Person : " + oPerson,
Toast.LENGTH_LONG).show();
System.out.println(oPerson);
cAddress.close();
return true;
}
else cAddress.moveToNext();
}
}
cAddress.close();
return false;
}
The result is
Person : John
It's Match! null
Actually, "It's Match! John"
Please check my mistake.
I am used to doing the following in C:
void main() {
String zText = "";
fillString(zText);
printf(zText);
}
void fillString(String zText) {
zText += "foo";
}
And the output is:
foo
However, in Java, this does not seem to work. I assume because the String object is copied instead of passed by referenced. I thought Strings were objects, which are always passed by reference.
What is going on here?
You have three options:
Use a StringBuilder:
StringBuilder zText = new StringBuilder ();
void fillString(StringBuilder zText) { zText.append ("foo"); }
Create a container class and pass an instance of the container to your method:
public class Container { public String data; }
void fillString(Container c) { c.data += "foo"; }
Create an array:
new String[] zText = new String[1];
zText[0] = "";
void fillString(String[] zText) { zText[0] += "foo"; }
From a performance point of view, the StringBuilder is usually the best option.
In Java nothing is passed by reference. Everything is passed by value. Object references are passed by value. Additionally Strings are immutable. So when you append to the passed String you just get a new String. You could use a return value, or pass a StringBuffer instead.
What is happening is that the reference is passed by value, i.e., a copy of the reference is passed. Nothing in java is passed by reference, and since a string is immutable, that assignment creates a new string object that the copy of the reference now points to. The original reference still points to the empty string.
This would be the same for any object, i.e., setting it to a new value in a method. The example below just makes what is going on more obvious, but concatenating a string is really the same thing.
void foo( object o )
{
o = new Object( ); // original reference still points to old value on the heap
}
java.lang.String is immutable.
I hate pasting URLs but https://docs.oracle.com/javase/10/docs/api/java/lang/String.html is essential for you to read and understand if you're in java-land.
All arguments in Java are passed by value. When you pass a String to a function, the value that's passed is a reference to a String object, but you can't modify that reference, and the underlying String object is immutable.
The assignment
zText += foo;
is equivalent to:
zText = new String(zText + "foo");
That is, it (locally) reassigns the parameter zText as a new reference, which points to a new memory location, in which is a new String that contains the original contents of zText with "foo" appended.
The original object is not modified, and the main() method's local variable zText still points to the original (empty) string.
class StringFiller {
static void fillString(String zText) {
zText += "foo";
System.out.println("Local value: " + zText);
}
public static void main(String[] args) {
String zText = "";
System.out.println("Original value: " + zText);
fillString(zText);
System.out.println("Final value: " + zText);
}
}
prints:
Original value:
Local value: foo
Final value:
If you want to modify the string, you can as noted use StringBuilder or else some container (an array or an AtomicReference or a custom container class) that gives you an additional level of pointer indirection. Alternatively, just return the new value and assign it:
class StringFiller2 {
static String fillString(String zText) {
zText += "foo";
System.out.println("Local value: " + zText);
return zText;
}
public static void main(String[] args) {
String zText = "";
System.out.println("Original value: " + zText);
zText = fillString(zText);
System.out.println("Final value: " + zText);
}
}
prints:
Original value:
Local value: foo
Final value: foo
This is probably the most Java-like solution in the general case -- see the Effective Java item "Favor immutability."
As noted, though, StringBuilder will often give you better performance -- if you have a lot of appending to do, particularly inside a loop, use StringBuilder.
But try to pass around immutable Strings rather than mutable StringBuilders if you can -- your code will be easier to read and more maintainable. Consider making your parameters final, and configuring your IDE to warn you when you reassign a method parameter to a new value.
objects are passed by reference, primitives are passed by value.
String is not a primitive, it is an object, and it is a special case of object.
This is for memory-saving purpose. In JVM, there is a string pool. For every string created, JVM will try to see if the same string exist in the string pool, and point to it if there were already one.
public class TestString
{
private static String a = "hello world";
private static String b = "hello world";
private static String c = "hello " + "world";
private static String d = new String("hello world");
private static Object o1 = new Object();
private static Object o2 = new Object();
public static void main(String[] args)
{
System.out.println("a==b:"+(a == b));
System.out.println("a==c:"+(a == c));
System.out.println("a==d:"+(a == d));
System.out.println("a.equals(d):"+(a.equals(d)));
System.out.println("o1==o2:"+(o1 == o2));
passString(a);
passString(d);
}
public static void passString(String s)
{
System.out.println("passString:"+(a == s));
}
}
/* OUTPUT */
a==b:true
a==c:true
a==d:false
a.equals(d):true
o1==o2:false
passString:true
passString:false
the == is checking for memory address (reference), and the .equals is checking for contents (value)
String is an immutable object in Java. You can use the StringBuilder class to do the job you're trying to accomplish, as follows:
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder("hello, world!");
System.out.println(sb);
foo(sb);
System.out.println(sb);
}
public static void foo(StringBuilder str)
{
str.delete(0, str.length());
str.append("String has been modified");
}
Another option is to create a class with a String as a scope variable (highly discouraged) as follows:
class MyString
{
public String value;
}
public static void main(String[] args)
{
MyString ms = new MyString();
ms.value = "Hello, World!";
}
public static void foo(MyString str)
{
str.value = "String has been modified";
}
The answer is simple. In java strings are immutable. Hence its like using 'final' modifier (or 'const' in C/C++). So, once assigned, you cannot change it like the way you did.
You can change which value to which a string points, but you can NOT change the actual value to which this string is currently pointing.
Ie. String s1 = "hey". You can make s1 = "woah", and that's totally ok, but you can't actually change the underlying value of the string (in this case: "hey") to be something else once its assigned using plusEquals, etc. (ie. s1 += " whatup != "hey whatup").
To do that, use the StringBuilder or StringBuffer classes or other mutable containers, then just call .toString() to convert the object back to a string.
note: Strings are often used as hash keys hence that's part of the reason why they are immutable.
String is a special class in Java. It is Thread Safe which means "Once a String instance is created, the content of the String instance will never changed ".
Here is what is going on for
zText += "foo";
First, Java compiler will get the value of zText String instance, then create a new String instance whose value is zText appending "foo". So you know why the instance that zText point to does not changed. It is totally a new instance. In fact, even String "foo" is a new String instance. So, for this statement, Java will create two String instance, one is "foo", another is the value of zText append "foo".
The rule is simple: The value of String instance will never be changed.
For method fillString, you can use a StringBuffer as parameter, or you can change it like this:
String fillString(String zText) {
return zText += "foo";
}
Strings are immutable in Java.
This works use StringBuffer
public class test {
public static void main(String[] args) {
StringBuffer zText = new StringBuffer("");
fillString(zText);
System.out.println(zText.toString());
}
static void fillString(StringBuffer zText) {
zText .append("foo");
}
}
Even better use StringBuilder
public class test {
public static void main(String[] args) {
StringBuilder zText = new StringBuilder("");
fillString(zText);
System.out.println(zText.toString());
}
static void fillString(StringBuilder zText) {
zText .append("foo");
}
}
String is immutable in java. you cannot modify/change, an existing string literal/object.
String s="Hello";
s=s+"hi";
Here the previous reference s is replaced by the new refernce s pointing to value "HelloHi".
However, for bringing mutability we have StringBuilder and StringBuffer.
StringBuilder s=new StringBuilder();
s.append("Hi");
this appends the new value "Hi" to the same refernce s.
//
Aaron Digulla has the best answer so far. A variation of his second option is to use the wrapper or container class MutableObject of the commons lang library version 3+:
void fillString(MutableObject<String> c) { c.setValue(c.getValue() + "foo"); }
you save the declaration of the container class. The drawback is a dependency to the commons lang lib. But the lib has quite a lot of useful function and almost any larger project i have worked on used it.
For passing an object (including String) by reference in java, you might pass it as member of a surrounding adapter. A solution with a generic is here:
import java.io.Serializable;
public class ByRef<T extends Object> implements Serializable
{
private static final long serialVersionUID = 6310102145974374589L;
T v;
public ByRef(T v)
{
this.v = v;
}
public ByRef()
{
v = null;
}
public void set(T nv)
{
v = nv;
}
public T get()
{
return v;
}
// ------------------------------------------------------------------
static void fillString(ByRef<String> zText)
{
zText.set(zText.get() + "foo");
}
public static void main(String args[])
{
final ByRef<String> zText = new ByRef<String>(new String(""));
fillString(zText);
System.out.println(zText.get());
}
}
For someone who are more curious
class Testt {
static void Display(String s , String varname){
System.out.println(varname + " variable data = "+ s + " :: address hashmap = " + s.hashCode());
}
static void changeto(String s , String t){
System.out.println("entered function");
Display(s , "s");
s = t ;
Display(s,"s");
System.out.println("exiting function");
}
public static void main(String args[]){
String s = "hi" ;
Display(s,"s");
changeto(s,"bye");
Display(s,"s");
}
}
Now by running this above code you can see how address hashcodes change with String variable s .
a new object is allocated to variable s in function changeto when s is changed