在Java中交换两个字符串,方法是将它们传递给实用程序函数,但不返回对象或使用包装类

我试图在Java中交换两个字符串。 我从未真正理解“字符串是不可变的”。 我在理论上理解它,但我在实践中从未遇到过它。

此外,由于String是Java中的对象而不是基本类型,我不明白为什么以下代码两次打印相同的结果,而不是交换单词!

public static void main(String[] args) { String s1 = "Hello"; String s2 = "World"; System.out.println(s1 + " " + s2); Swap(s1, s2); System.out.println(s1 + " " + s2); } public static void Swap(String s1, String s2) { String temp = s1; s1 = s2; s2 = temp; } 

我想要它打印

 Hello World World Hello 

但它是印刷品

 Hello World Hello World 

我认为s1和s2是引用,因此应该交换引用,新引用应分别指向另一个引用。 我哪里错了?

我认为s1和s2是引用,因此应该交换引用,新引用应分别指向另一个引用。

是。 在本地内部 swap ,这正是发生的事情。

但是, s1s2是传递给函数的引用的副本 ,因此效果保持为本地。 请注意,它不是复制的字符串(因为String是引用类型)。 但是复制了引用。

…并且由于参数引用总是在Java中复制,因此根据您的规范编写swap函数是非常简单的。

如果您在理解差异时遇到问题,请考虑以下事项:您想给朋友写一封信,以便将邮寄地址从地址簿复制到信封上。 通过这个过程,你当然没有复制她的家(复制整个房子在实践中有点困难) – 你只复制了地址。

好吧,一个地址指的是她的家,所以它就像一个Java引用。

下面的代码是NoGo ,从不实现这种反模式,永远不会改变不可变对象的私有最终内部。 不要责怪我表现出这种黑客行为,责怪甲骨文公司因为不接受它而拒绝接受。

但是,如果有一天你找到一些代码可以工作:

  String a = "Hello"; String b = "World"; String c = "World"; swap(a,b); System.out.printf("%s %s%n", a,b); // prints: World Hello !! System.out.println(c); // Side effect: prints "Hello" instead of "World".... 

swap的实现可能如下所示:(自行承担风险,我警告过你!)

  private void swap(String a, String b) { try { Field value = String.class.get("value"); value.setAccessible(true); // this should be forbidden!! char[] temp = value.get(a); value.set(a, value.get(b)); value.set(b, temp); // Aaargh, please forgive me } catch(Exception e) { e.printStackTrace(e); } } 

基本上,您无法在Java中实现swap方法。

你不能这样做的原因是Java参数具有按值传递的参数语义。 因此,当你的swap方法将s2分配给s1等时,它完全依赖于局部变量s1s2 ,而不是调用方法mains1s2变量。

相比之下,如果你要在C中实现swap方法,它看起来像这样:

 void swap(char ** s1, char ** s2) { char * temp = *s1; *s1 = *s2; *s2 = temp; } 

你会这样称呼它:

 char *s1 = "Hello World"; char *s2 = "Goodbye World"; swap(&s1, &s2); 

请注意,我们实际上是在传递“指向char”指针变量的地址。

在Java中,您无法执行此操作,因为您无法获取变量的地址。 它根本不受支持。

最近有一个关于交换两个整数的非常类似的问题 。 我的答案是使用primefaces参考 :

 public void swap(AtomicReference a, AtomicReference b){ // update: look mom, no variables a.set(b.getAndSet(a.get())); } 

当然这不是很令人满意,因为你几乎没有针对AtomicReferences开发。 但基本上你需要使用某种容器,因为你不能只是交换引用。 所以你可以例如交换双元素数组或列表的元素,但是你无法交换两个字符串而无法访问原始变量(所以你不能在辅助函数中做到这一点)。

Java String是通过引用实现的,因此您需要交换它们的引用。

 String s1 = "Hello"; String s2 = "World"; AtomicReference String1 = new AtomicReference(s1); AtomicReference String2 = new AtomicReference(s2); String1.set(String2.getAndSet(String1.get())); System.out.println(String1 + " " + String2); 

它会给你这个输出:

 World Hello 

函数交换中的s1和s2变量是该函数的本地变量。

您需要将s1和s2定义为类的私有变量,或者从函数返回一个字符串数组。

由于Java使用pass-by-value,因此您定义的交换函数不进行任何类型的交换; 指针s1和s2在本地交换,但交换的结果不会持久。 您可以实现的最接近的事情是将要交换的项包装在某个类中,并在该类中定义交换方法。 这将允许您在此类的实例之间交换数据,尽管它实际上不会交换基础数据。 作为一个例子:

  public class Swapper { public Swapper(T obj) { data_ = obj; } public T get() { return data_; } public void set(T value) { data_ = value; } public void swap(Swapper o) { T tmp = o.data_; o.data_ = data_; data_ = tmp; } private T data_ = null; } // .. Now you can do: Swapper a = new Swapper("Hello"); Swapper b = new Swapper("World"); // a.get().equals("Hello") a.swap(b); // now a.get().equals("World") 
 String s1 = "Hello"; String s2 = "World"; s1=s1+" "+s2; s2=s1.split(" ")[0]; s1=s1.split(" ")[1]; System.out.println(s1 + " " + s2); 

通过使用StringBufferReaderStringBuilder可以解决这个问题。 在1st获取用户的值然后拆分它们并将它们存储在数组中。 以相反的顺序运行for循环,以便最后添加最后一个字符串并显示第一个字符串。 输入:hello world输出:

 import java.io.*; import java.util.*; import java.lang.*; public class Solution { public static void main(String[] args) { try { int s,i,j; StringBuilder str = new StringBuilder(); String st,t; BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); t = br.readLine(); s = Integer.parseInt(t); for (i = 0; i < s; i++) { st=br.readLine(); String st1[]=st.split("\\s+"); // System.out.println("l="+st1.length); for (j = st1.length - 1; j >= 0; j--) { str.append(st1[j] + " "); } System.out.println(str); str.setLength(0); } } catch (Exception e) { System.out.println(e); } } }