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

发布于 2024-09-18 20:21:01 字数 647 浏览 8 评论 0原文

我正在尝试在 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 是引用,因此引用应该交换,新的引用应该分别指向另一个。我哪里出错了?

I am trying to swap two strings in Java. I never really understood "strings are immutable". I understand it in theory, but I never came across it in practice.

Also, since String is an object in Java and not a primitive type, I don't understand why the following code prints the same result twice, instead of interchanging the words!

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;
}

I want it to print

Hello World
World Hello

But it is printing

Hello World
Hello World

I thought s1 and s2 are references and hence the references should be swapped and the new ones should point to the other one respectively. Where am I going wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

初相遇 2024-09-25 20:21:02

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

是的。在本地内部交换中,这正是发生的情况。

但是,s1s2 是传递到函数中的引用的副本,因此效果仍然是本地的。请注意,复制的不是字符串(因为 String 是引用类型)。但引用被复制了。

…并且由于参数引用总是在Java中复制,因此根据您的规范编写交换函数很简单,是不可能的。

如果您无法理解其中的区别,请考虑以下情况:您想给朋友写一封信,因此您将她的邮政地址从地址簿复制到信封上。通过这个过程,你当然没有复制她的家(复制整个房子在实践中有点困难)——你只是复制了地址。

嗯,地址指的是她的家,因此它与 Java 引用完全相同。

I thought s1 and s2 are references and hence the references should be swapped and the new ones should point to the other one respectively.

Yes. Locally inside swap, this is exactly what happens.

However, s1 and s2 are copies of the references passed into the function, so the effect remains local. Note that it’s not the strings that are copied (since String is a reference type). But the references are copied.

… and since parameter references are always copied in Java, writing a swap function according to your specifications is, quite simply, not possible.

If you have problems understanding the difference, consider this: you want to write a letter to a friend so you copy her postal address from your address book onto an envelope. By this process, you certainly didn’t copy her home (copying a whole house is a bit difficult in practice) – you only copied the address.

Well, an address refers to her home so it’s exactly like a Java reference.

自由如风 2024-09-25 20:21:02

下面的代码是NoGo,永远不要实现这个反模式,永远不要改变不可变对象上的私有最终内部结构。不要责怪我展示了这个 hack,责怪 Oracle 的 jvm 没有禁止它。

但是,如果有一天您发现一些代码可以正常工作:

 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"....

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

 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);
   }
 }

The following code is a NoGo, never implement this anti pattern, never ever ever ever change private final internals on immutable objects. Don't blame me for showing this hack, blame Oracle's jvm for not disallowing it.

But, if one day you find some code where this works:

 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"....

the implementation of swap could look like this: (read on your own risk, I warned you!)

 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);
   }
 }
灰色世界里的红玫瑰 2024-09-25 20:21:02

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

不能这样做的原因是 Java 参数具有按值传递参数语义。因此,当您的 swap 方法将 s2 分配给 s1 等时,它完全在本地变量上运行< code>s1 和 s2,而不是调用方法 mains1 和 s2 变量>。

相比之下,如果您要在 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 中,您不能这样做,因为您无法获取变量的地址。它根本不受支持。

Basically, you cannot implement swap method in Java.

The reason you cannot do this is that Java argument has pass-by-value argument semantics. So when your swap method assigns s2 to s1 and so on, it is operating entirely on the local variables s1 and s2, and NOT on the s1 and s2 variables in the calling method main.

By contrast, if you were to implement the swap method in C, it would look something like this:

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

and you would call it like this:

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

Notice that we are actually passing the address of a "pointer to char" variable.

In Java, you cannot do this because you cannot take the address of a variable. It is simply not supported.

伪心 2024-09-25 20:21:02

最近有一个关于交换两个的一个非常类似的问题整数。 我的答案是使用原子引用

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

当然,这不是很令人满意,因为您几乎不会针对 AtomicReferences 进行开发。但基本上你需要使用某种容器,因为你不能仅仅交换引用。因此,您可以交换二元素数组或列表的元素,但在无法访问原始变量的情况下无法交换两个字符串(因此您无法在辅助函数中执行此操作)。

There was a very similar question recently about swapping two ints. And my answer then was to use atomic references:

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

Of course this not very satisfactory, as you hardly ever develop against AtomicReferences. But basically you need to use some kind of container because you can't just swap the references. So you can e.g. swap the elements of a two-element array or list, but you just can't swap two strings without having access to the original variables (so you can't do it in a helper function).

吻泪 2024-09-25 20:21:02

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

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

它会给你这个输出:

World Hello

Java Strings are implemented with references, so you need to swap their references.

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

It will give you this output:

World Hello
白昼 2024-09-25 20:21:02

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

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

The s1 and s2 variables in your function swap are local to that function.

You need to define s1 and s2 as private variables for your class, or return an array of strings from your function.

梦与时光遇 2024-09-25 20:21:02

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

  public class Swapper<T> {
      public Swapper(T obj) {
             data_ = obj;
      }
      public T get() { return data_; }
      public void set(T value) { data_ = value; }
      public void swap(Swapper<T> o) {
           T tmp = o.data_;
           o.data_ = data_;
           data_ = tmp;
      }
      private T data_ = null;
  }

  // .. Now you can do:
  Swapper<String> a = new Swapper("Hello");
  Swapper<String> b = new Swapper("World");
  // a.get().equals("Hello")
  a.swap(b); // now a.get().equals("World")

Since Java uses pass-by-value, the swap function that you have defined does not do any sort of swapping; the pointers s1 and s2 are swapped locally, but the result of the swap does not persist. The closest thing you can achieve is to wrap the items you want to swap in some class and define a swap method in that class. This will allow you to swap data between instances of this class, although it will not actually swap the underlying data. As an example of this:

  public class Swapper<T> {
      public Swapper(T obj) {
             data_ = obj;
      }
      public T get() { return data_; }
      public void set(T value) { data_ = value; }
      public void swap(Swapper<T> o) {
           T tmp = o.data_;
           o.data_ = data_;
           data_ = tmp;
      }
      private T data_ = null;
  }

  // .. Now you can do:
  Swapper<String> a = new Swapper("Hello");
  Swapper<String> b = new Swapper("World");
  // a.get().equals("Hello")
  a.swap(b); // now a.get().equals("World")
初相遇 2024-09-25 20:21:02
String s1 = "Hello";
String s2 = "World";
    s1=s1+" "+s2;
s2=s1.split(" ")[0];
s1=s1.split(" ")[1];
System.out.println(s1 + " " + s2);
String s1 = "Hello";
String s2 = "World";
    s1=s1+" "+s2;
s2=s1.split(" ")[0];
s1=s1.split(" ")[1];
System.out.println(s1 + " " + s2);
澉约 2024-09-25 20:21:02

通过使用 StringBufferReader 和 StringBuilder 可以解决这个问题。首先从用户那里获取值,然后将它们拆分并存储在数组中。以相反的顺序运行 for 循环,以便最后一个字符串将被附加并首先显示,第一个字符串将最后显示。
输入:你好世界
输出:

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);
    }
  }
}

By using StringBufferReader and StringBuilder this can be solved. At 1st get the values from the user then split them and store them in array. Run the for loop in the reverse order so that the last string will be appended and displayed 1st the first will displayed last.
input:hello world
output:

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);
    }
  }
}
陈甜 2024-09-25 20:21:02

Java将内存中对象的地址传递给函数。然后函数中的某个局部变量保存该地址。如果您为这些局部变量分配一些新地址(另一个对象),则原始对象没有理由改变。

但是,将应用对原始对象的字段以及现有地址的更改。 (与c/c++中的.运算符相关)

此链接 也可能有帮助。

Java passes the address of objects in the memory to functions. Then some local variable in the function holds that address. There is no reason for the original object to change if you assign some new address (another object) to those local variables.

However, changes to the fields of the original object, with the address in hand, ARE applied. (relate to . operator in c/c++)

This link may also help.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文