尽管是字符数组,为什么 String 不能像 "pass by reference" 一样工作
Why does String not work as "pass by reference" in spite of being an array of characters
我了解将数组作为参数传递给函数,并在函数内部对数组元素进行一些更改时,这些更改也会反映在调用函数中,因为数组直接在内存上运行(参考调用)
但是,为什么相同的行为不适用于字符串?我期待字符串也能以同样的方式工作,因为字符串基本上是一个字符数组。
请看下面我的代码。
我将一个 String(字符数组)和一个 int 数组传入一个函数,并对其进行一些更改。在 main 中打印这些时,我看到 String 保持不受影响,而对数组的更改得到反映。
import java.util.Arrays;
public class TestString
{
public static void main(String[] args)
{
String s = "hello";
int[] a = new int[5];
Arrays.fill(a, -1);
fun(s,a);
System.out.println(s);
System.out.println(a[0]);
}
static void fun(String s, int[] a)
{
s = "world";
a[0] = 99;
}
}
输出
hello
99
因为 java 中的字符串是不可变的。对字符串的每一次 "change" 操作都不会改变原始字符串,而是创建一个新的 String 对象。
因为Strings
是不可变的。如果你想改变 String
的值,你应该从方法中 return 它并再次将它存储在变量 s
中。
import java.util.Arrays;
public class TestString
{
public static void main(String[] args)
{
String s = "hello";
int[] a = new int[5];
Arrays.fill(a, -1);
s = fun(s,a);
System.out.println(s);
System.out.println(a[0]);
}
static String fun(String s, int[] a)
{
s = "world";
a[0] = 99;
return s;
}
}
希望对您有所帮助!
Java 不是按引用调用,而是按值调用,只是它将引用作为值传递。 More details here.
字符串是不可变的,因此您无法更改字符串的内容(char 数组),您可以将其替换为不同的内容,即您正在更改引用。但由于引用是按值传递的,因此更改在方法外部不可见。
实际上,您可以使用反射更改 String 的内容,这会产生非常有趣的行为。只有当你想恶作剧同事时才使用它。
首先,String
是字符数组的说法是错误的。 String
是一个对象,它具有方法并且被设计为专门不允许对其进行任何更改。
其次,您所做的并没有改变参数的某些元素。您正在更改参数 变量 。参数变量基本上是一个 local 变量,它接收一个 reference 作为参数传递的字符串。这样做:
s = "world";
没有更改传递的字符串。它用新字符串替换局部变量 s
的内容。由于 Java 总是 按值传递,这不会反映在方法之外。如果你有:
a = new int[30];
方法内部。在它外面你仍然会看到你在里面传递的 5 元素 int[]
。
a[0] = 99;
正在更改数组中的 元素 。所以它查看 a
,检查它引用的内容,转到该引用的数组,并更改它的第 0 个元素。
由于String
被设计为不可变的,所以没有办法在其中做类似的事情。你不能做这样的事情:
s.setCharacter(0,'a'); // This doesn't exist in Java
但是您可以使用 可变 对象来做到这一点。例如,如果您有:
public static void manipulateStringBuilder( StringBuilder sb ) {
sb.append(": manipulated");
sb = new StringBuilder("New value assigned");
}
那么你可以这样写:
StringBuilder sb = new StringBuilder("My string");
System.out.println(sb);
manipulateStringBuilder( sb );
System.out.println(sb);
输出将是:
My string
My string: manipulated
这是因为 StringBuilder
是一个 可变的 对象,再加上您 分配 的值给 sb
在你的方法内部永远不会在它之外出现。
我了解将数组作为参数传递给函数,并在函数内部对数组元素进行一些更改时,这些更改也会反映在调用函数中,因为数组直接在内存上运行(参考调用)
但是,为什么相同的行为不适用于字符串?我期待字符串也能以同样的方式工作,因为字符串基本上是一个字符数组。
请看下面我的代码。 我将一个 String(字符数组)和一个 int 数组传入一个函数,并对其进行一些更改。在 main 中打印这些时,我看到 String 保持不受影响,而对数组的更改得到反映。
import java.util.Arrays;
public class TestString
{
public static void main(String[] args)
{
String s = "hello";
int[] a = new int[5];
Arrays.fill(a, -1);
fun(s,a);
System.out.println(s);
System.out.println(a[0]);
}
static void fun(String s, int[] a)
{
s = "world";
a[0] = 99;
}
}
输出
hello
99
因为 java 中的字符串是不可变的。对字符串的每一次 "change" 操作都不会改变原始字符串,而是创建一个新的 String 对象。
因为Strings
是不可变的。如果你想改变 String
的值,你应该从方法中 return 它并再次将它存储在变量 s
中。
import java.util.Arrays;
public class TestString
{
public static void main(String[] args)
{
String s = "hello";
int[] a = new int[5];
Arrays.fill(a, -1);
s = fun(s,a);
System.out.println(s);
System.out.println(a[0]);
}
static String fun(String s, int[] a)
{
s = "world";
a[0] = 99;
return s;
}
}
希望对您有所帮助!
Java 不是按引用调用,而是按值调用,只是它将引用作为值传递。 More details here.
字符串是不可变的,因此您无法更改字符串的内容(char 数组),您可以将其替换为不同的内容,即您正在更改引用。但由于引用是按值传递的,因此更改在方法外部不可见。
实际上,您可以使用反射更改 String 的内容,这会产生非常有趣的行为。只有当你想恶作剧同事时才使用它。
首先,String
是字符数组的说法是错误的。 String
是一个对象,它具有方法并且被设计为专门不允许对其进行任何更改。
其次,您所做的并没有改变参数的某些元素。您正在更改参数 变量 。参数变量基本上是一个 local 变量,它接收一个 reference 作为参数传递的字符串。这样做:
s = "world";
没有更改传递的字符串。它用新字符串替换局部变量 s
的内容。由于 Java 总是 按值传递,这不会反映在方法之外。如果你有:
a = new int[30];
方法内部。在它外面你仍然会看到你在里面传递的 5 元素 int[]
。
a[0] = 99;
正在更改数组中的 元素 。所以它查看 a
,检查它引用的内容,转到该引用的数组,并更改它的第 0 个元素。
由于String
被设计为不可变的,所以没有办法在其中做类似的事情。你不能做这样的事情:
s.setCharacter(0,'a'); // This doesn't exist in Java
但是您可以使用 可变 对象来做到这一点。例如,如果您有:
public static void manipulateStringBuilder( StringBuilder sb ) {
sb.append(": manipulated");
sb = new StringBuilder("New value assigned");
}
那么你可以这样写:
StringBuilder sb = new StringBuilder("My string");
System.out.println(sb);
manipulateStringBuilder( sb );
System.out.println(sb);
输出将是:
My string My string: manipulated
这是因为 StringBuilder
是一个 可变的 对象,再加上您 分配 的值给 sb
在你的方法内部永远不会在它之外出现。