【问题标题】:Java string value change in function函数中的Java字符串值变化
【发布时间】:2011-03-30 00:30:12
【问题描述】:

我有一个非常尴尬的问题...

void changeString(String str){
    str = "Hello world":
}

main(){
    String myStr = new String("");
    changeString(myStr);
}

main 返回时,值仍然是"" 而不是"Hello world"。这是为什么呢?

另外,我该如何让它工作?假设我希望我的函数 changeString 将它得到的字符串更改为“Hello world”。

【问题讨论】:

    标签: java string function pass-by-reference


    【解决方案1】:

    Java 使用call by value startegy 来评估调用。

    也就是说,该值被复制到str,因此如果您分配给str,则不会更改原始值。

    【讨论】:

      【解决方案2】:

      因为引用 myStr 是按值传递给函数 changeString 并且更改不会反映回调用函数。

      P.S : 我不是 Java 人。

      【讨论】:

      • 我没有投反对票,但是“更改没有反映回来”这句话可能会产生误导。一些变化,取决于语义,ARE 反射回来。按值传递意味着没有副作用绝对不是真的(这也是一些初学者混淆的根源,例如传递数组引用并使其元素可通过方法修改)。
      【解决方案3】:

      每个人都解释了为什么它不起作用,但没有人解释如何使它起作用。您最简单的选择是使用:

      String changeString() {
          return "Hello world";
      }
      
      main() {
      
          String myStr = new String("");
          myStr = changeString();
      }
      

      虽然方法名称在这里用词不当。如果你要使用你最初的想法,你需要这样的东西:

      void changeString(ChangeableString str) {
          str.changeTo("Hello world");
      }
      
      main() {
      
          ChangeableString myStr = new ChangeableString("");
          changeString(myStr);
      }
      

      你的ChangeableString 类可能是这样的:

      class ChangeableString {
          String str;
          
          public ChangeableString(String str) {
              this.str = str;
          }
      
          public void changeTo(String newStr) {
              str = newStr;
          }
      
          public String toString() {
              return str;
          }
      }
      

      关于参考的快速课程:

      在 Java 方法中,一切都是按值传递的。这包括参考。这可以通过以下两种不同的方法来说明:

      void doNothing(Thing obj) {
          obj = new Something();
      }
      
      void doSomething(Thing obj) {
          obj.changeMe();
      }
      

      如果您从main()(或其他任何地方)调用doNothing(obj),则obj 不会在被调用者中更改,因为doNothing 创建了一个新的Thing,并将该新引用分配给@987654331 @在方法的范围内

      另一方面,在 doSomething 中,您正在调用 obj.changeMe(),并且取消引用 obj(按值传递)并更改它。

      【讨论】:

      • 可能很挑剔,但您的第二个解决方案将不起作用,因为 String 是最终类(您不能将 String 变量分配给 ChangeableString)。它可能会帮助 OP 了解您将如何定义 ChangeableString。
      • @anov "you can't assign a String variable to a ChangeableString" 我在哪里做呢?
      • 谢谢!实际上,我的 func 确实返回了一个值,因此我无法从中返回新字符串。至于第二种解决方案(使用 ChangeableString),这是一个很好的解决方案。但是,我不想弄乱我的代码并只为一个调用添加这个类。这真的很烦人,如果我使用没有构建一些“set”函数的 Java 类,我真的必须使用创建另一个容器的解决方案来传递它吗?是不是有一些解决方法可以通过 & 传递它?!为每个没有“设置”或“更改”功能的类编写一个容器真的不好......
      • @Yura 我想我们都应该问的真正问题是为什么您要更改myStr 参考。最好将其设为包含 main() 方法的类的成员变量。
      • @Yura 如果没有看到更具代表性的代码示例,很难提供帮助,但从您的说法看来,您的代码需要重构。使用char[](或只包含一个String!的String[])只是解决问题而不是纠正问题的一种方法。如果你习惯了 C++ 习语,我理解这种诱惑,但这会阻碍你学习新语言的进度。
      【解决方案4】:

      如果您的String 的更改经常发生,您还可以将StringBufferStringBuilder 分配给您的变量并更改其内容,并仅在需要时将其转换为String

      【讨论】:

        【解决方案5】:

        NullUserException's excellent answer 上扩展一点,这里有一个更通用的解决方案:

        public class Changeable<T> {
           T value;
        
           public Changeable(T value) {
              this.value = value;
           }
        
           public String toString() {
              return value.toString();
           }
        
           public boolean equals(Object other) {
              if (other instanceof Changeable) {
                 return value.equals(((Changeable)other).value);
              } else {
                 return value.equals(other);
              }
           }
        
           public int hashCode() {
              return value.hashCode();
           }
        }
        

        Yura 的原始代码可以改写为:

        void changeString(Changeable<String> str){
           str.value = "Hello world":
        }
        
        void main() {
           Changeable<String> myStr = new Changeable<String>("");
           changeString(myStr);
        }
        

        而且,只是为了好玩,这里是Scala

        class Changeable[T](var self: T) extends Proxy;
        
        object Application {
           def changeString(str: Changeable[String]): Unit = {
              str.self = "Hello world";
           }
        
           def main(): Unit = {
              val myStr = new Changeable("");
              changeString(myStr);
           }
        }
        

        【讨论】:

          【解决方案6】:

          Bill,我有一个解决您的问题的方法,它在 java 中使用 List 作为指针!

          void changeString(List<String> strPointer ){
              String str = "Hello world";
              strPointer.add(0, str);
          }
          
          main(){
              LinkedList<String> list = new LinkedList<String>();
              String myStr = new String("");
              changeString(list);
              myStr = list.get(0);
              System.out.println( myStr );
          }
          

          这个答案需要一些额外的工作来从列表中插入和取出字符串,但是最后一行将打印“Hello world!”

          我希望这也可以帮助其他人!

          -端口转发播客

          【讨论】:

            【解决方案7】:

            这是StringBuffer/StringBuilder 为我工作的另一个解决方案。

            static void changeValue(StringBuilder str){
                str.append("newValue");
            }
            
            main(){
                StringBuilder originalVal= new StringBuilder();
                changeValue(originalVal);
                System.out.println(originalVal.toString());
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-08-25
              • 2019-10-08
              • 2016-03-28
              • 1970-01-01
              相关资源
              最近更新 更多