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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3698323/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 03:37:29  来源:igfitidea点击:

Swap two strings in Java, by passing them to a utility function, but without returning objects or using wrapper classes

javastringpass-by-reference

提问by

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.

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

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!

另外,由于 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;
}

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?

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

采纳答案by Konrad Rudolph

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.

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

Yes. Locally insideswap, this is exactly what happens.

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

However, s1and s2are copiesof the references passed into the function, so the effect remains local. Note that it's not the strings that are copied (since Stringis a reference type). But the references arecopied.

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

… and since parameter references are alwayscopied in Java, writing a swapfunction according to your specifications is, quite simply, not possible.

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

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 refersto her home so it's exactly like a Java reference.

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

回答by Stephen C

Basically, you cannot implement swapmethod in Java.

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

The reason you cannot do this is that Java argument has pass-by-value argument semantics. So when your swapmethod assigns s2to s1and so on, it is operating entirely on the localvariables s1and s2, and NOT on the s1and s2variables in the calling method main.

您不能这样做的原因是 Java 参数具有按值传递参数语义。因此,当您的swap方法分配s2s1等等时,它完全对局部变量s1and 进行操作s2,而不是对调用方法中的s1ands2变量进行操作main

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

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

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.

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

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

在 Java 中,您不能这样做,因为您无法获取变量的地址。它根本不受支持。

回答by James Anderson

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

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

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

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

回答by Michael Aaron Safyan

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:

由于 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")

回答by Sean Patrick Floyd

There was a very similar questionrecently about swapping two ints. And my answer thenwas 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).

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

回答by Andreas Dolk

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.

下面的代码是一个NoGo,永远不会实现这种反模式,永远不会改变不可变对象的私有 final 内部。不要怪我展示这个 hack,怪 Oracle 的 jvm 没有禁止它。

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 swapcould look like this: (read on your own risk, I warned you!)

的实现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);
   }
 }

回答by Atul

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

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

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

回答by ashish

String s1 = "Hello";
String s2 = "World";
    s1=s1+" "+s2;
s2=s1.split(" ")[0];
s1=s1.split(" ")[1];
System.out.println(s1 + " " + s2);

回答by Vijay Krishna

By using StringBufferReaderand StringBuilderthis 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:

通过使用StringBufferReaderStringBuilder可以解决这个问题。首先从用户那里获取值,然后将它们拆分并将它们存储在数组中。以相反的顺序运行 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);
    }
  }
}