【问题标题】:Passing objects as references [duplicate]将对象作为引用传递[重复]
【发布时间】:2020-01-06 14:10:56
【问题描述】:
import java.util.HashSet;
import java.util.Set;
public class Main {
    public static void main(String[] args) {
        String input = "original input";
        Set<String> test = new HashSet<>();
        test.add(input);
        input = "modified input";
        test.stream().forEach(name -> System.out.println(name));
        System.out.println(input);
    }
}

输出:

original input
modified input

在通过结构读取字符串对象并直接读取对象时,我可以将此字符串对象作为参考传递给 Java 中的任何结构,并且两个输出将是相同的modified input

【问题讨论】:

  • 可以用StringBuffer或者StringBuilder来代替String来实现。

标签: java


【解决方案1】:

不适用于String,因为String 是不可变的。您可以修改您的方法以使用StringBuilder。喜欢,

StringBuilder input = new StringBuilder("original input");
Set<StringBuilder> test = new HashSet<>();
test.add(input);
input.setLength(0);
input.append("modified input");
test.stream().forEach(name -> System.out.println(name));
System.out.println(input);

输出(按要求)

modified input
modified input

【讨论】:

    【解决方案2】:

    没有。 Java 没有特殊的结构来传递String 作为引用,因为String 是不可变的并且不能被修改(每次你修改String一个新的字符串创建)。

    要在新方法中修改String,您必须获取原始字符串,构建一个新的和修改后的String 实例并检索它:

    public static void main(String... args) {
        String str = "original string"; // str = original string
        str = updateString(str);        // str = original string_smth.new
    
    }
    
    private static String updateString(String str) {
        return str + "_smth.new";
    }
    

    作为替代方案,您可以构建自定义包装器并使用它:

    public static void main(String... args) {
        StringWrapper str = new StringWrapper("original string");   // str = original string
        updateString(str);              r = original string_smth.new
    
    }
    
    private static void updateString(StringWrapper str) {
        str.set(str.get() + "_smth.new");
    }
    
    private static final StringWrapper {
        private String str;
    
        public StringWrapper(String str) {
            this.str = str;
        }
    
        public String get() {
            return str;
        }
    
        public void set(String str) {
            this.str = str;
        }
    
        public String toString() {
            return str;
        }
    }
    

    【讨论】:

      【解决方案3】:

      Java 没有变量引用,没有。你能做的就是把它包装在一个可变对象中:

      class Wrapper {
          private String value;
          Wrapper(String v) {
              this.value = v;
          }
          String getValue() {
              return this.value;
          }
          void setValue(String v) {
              this.value = v;
          }
      }
      

      然后:

      public static void main(String[] args) {
          String input = new Wrapper("original input");
      
          Set<Wrapper> test = new HashSet<>();
      
          test.add(input);
      
          input.setValue("modified input");
      
          test.stream().forEach(name -> System.out.println(name.getValue()));
      
          System.out.println(input.getValue());
      }
      

      集合中的值(对Wrapper 对象的引用)不会改变,但你会改变它所引用的对象的状态

      【讨论】:

        【解决方案4】:

        当你做这样的事情时:

        String input = "original input";
        

        这意味着您正在字符串池中创建一个新字符串: https://www.java67.com/2014/08/difference-between-string-literal-and-new-String-object-Java.html

        然后,当您尝试像这样重新分配它时:

        input = "modified input";
        

        这仅意味着您在字符串池中再创建一个字符串并将“输入”作为对新字符串的引用。

        因此,将旧字符串添加到集合 - 您正在将字符串的内存地址值添加到该集合对象:https://www.javaworld.com/article/2077424/learn-java-does-java-pass-by-reference-or-pass-by-value.html 结果,它不知道未来对输入的操作。

        总结:要做,你需要什么,你必须使用一些对象来存储你的字符串

        【讨论】:

          猜你喜欢
          • 2013-04-22
          • 2014-05-01
          • 1970-01-01
          • 2018-08-02
          • 1970-01-01
          • 2018-07-18
          • 2016-07-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多