在 Java 中通过引用传递字符串?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1270760/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Passing a String by Reference in Java?
提问by Soren Johnson
I am used to doing the following in C
:
我习惯于在以下内容中执行以下操作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 copiedinstead of passed by referenced. I thought Strings were objects, which are always passed by reference.
但是,在 Java 中,这似乎不起作用。我假设是因为String
对象被复制而不是通过引用传递。我认为字符串是对象,它们总是通过引用传递。
What is going on here?
这里发生了什么?
回答by Ryan Fernandes
java.lang.String is immutable.
java.lang.String 是不可变的。
I hate pasting URLs but https://docs.oracle.com/javase/10/docs/api/java/lang/String.htmlis essential for you to read and understand if you're in java-land.
我讨厌粘贴 URL,但https://docs.oracle.com/javase/10/docs/api/java/lang/String.html对您阅读和理解是否在 java 领域至关重要。
回答by Aaron Digulla
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"; }
使用 StringBuilder:
StringBuilder zText = new StringBuilder (); void fillString(StringBuilder zText) { zText.append ("foo"); }
创建一个容器类并将容器的实例传递给您的方法:
public class Container { public String data; } void fillString(Container c) { c.data += "foo"; }
创建一个数组:
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.
从性能的角度来看,StringBuilder 通常是最好的选择。
回答by zedoo
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.
在 Java 中,没有什么是通过引用传递的。一切都是按值传递的。对象引用按值传递。此外,字符串是不可变的。因此,当您附加到传递的字符串时,您只会得到一个新的字符串。您可以使用返回值,或者改为传递 StringBuffer。
回答by Ed S.
What is happening is that the reference is passed by value, i.e., a copyof 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 referencenow points to. The original reference still points to the empty string.
发生的事情是引用是按值传递的,即传递了引用的副本。java 中没有任何内容是通过引用传递的,并且由于字符串是不可变的,因此该赋值会创建一个新的字符串对象,引用的副本现在指向该对象。原始引用仍然指向空字符串。
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
}
回答by David Moles
All arguments in Java are passed by value. When you pass a String
to a function, the value that's passed isa reference to a String object, but you can't modify that reference, and the underlying String object is immutable.
Java 中的所有参数都是按值传递的。当您将 a 传递String
给函数时,传递的值是对 String 对象的引用,但您无法修改该引用,并且底层 String 对象是不可变的。
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.
也就是说,它(本地)将参数重新分配zText
为一个新的引用,它指向一个新的内存位置,其中是一个String
包含zText
with "foo"
append的原始内容的new 。
The original object is not modified, and the main()
method's local variable zText
still points to the original (empty) string.
原始对象没有被修改,main()
方法的局部变量zText
仍然指向原始(空)字符串。
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:
如果您想修改字符串,您可以按照说明使用StringBuilder
或其他一些容器(数组或AtomicReference
自定义容器类)为您提供额外的指针间接级别。或者,只需返回新值并分配它:
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 Javaitem "Favor immutability."
在一般情况下,这可能是最类似于 Java 的解决方案——请参阅Effective Java项目“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
.
但是,如前所述,StringBuilder
通常会给您带来更好的性能——如果您有很多附加工作要做,尤其是在循环内,请使用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.
但是,如果可以,请尝试传递不可变Strings
而不是可变StringBuilders
- 您的代码将更易于阅读且更易于维护。考虑制作参数final
,并配置 IDE 以在您将方法参数重新分配给新值时发出警告。
回答by DeepNightTwo
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 ".
String 是 Java 中的一个特殊类。它是线程安全的,这意味着“一旦创建了 String 实例,String 实例的内容将永远不会改变”。
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.
首先,Java 编译器会获取 zText String 实例的值,然后创建一个新的 String 实例,其值为 zText 附加“foo”。所以你知道为什么 zText 指向的实例没有改变。这完全是一个新实例。事实上,即使是 String "foo" 也是一个新的 String 实例。所以,对于这个语句,Java 会创建两个 String 实例,一个是“foo”,另一个是 zText append 的值“foo”。规则很简单:String 实例的值永远不会改变。
For method fillString, you can use a StringBuffer as parameter, or you can change it like this:
对于方法 fillString,您可以使用 StringBuffer 作为参数,也可以像这样更改它:
String fillString(String zText) {
return zText += "foo";
}
回答by janetsmith
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.
String 不是基元,它是一个对象,它是对象的一个特例。
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.
这是为了节省内存。在JVM中,有一个字符串池。对于创建的每个字符串,JVM 将尝试查看字符串池中是否存在相同的字符串,如果已经存在则指向它。
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)
== 正在检查内存地址(引用),而 .equals 正在检查内容(值)
回答by Mohammed Rafeeq
This works use StringBuffer
这个作品使用 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
更好地使用 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");
}
}
回答by Fadi Hanna AL-Kass
String is an immutable object in Java. You can use the StringBuilder class to do the job you're trying to accomplish, as follows:
String 是 Java 中的不可变对象。您可以使用 StringBuilder 类来完成您要完成的工作,如下所示:
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:
另一种选择是创建一个以 String 作为作用域变量的类(非常不鼓励),如下所示:
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";
}