Java 变量参数传入方法,修改后是否影响外面的值

今天在公司做的一个订购成功后发送给用户的邮件时,见到了之前别人留下来的一个问题。类似于下面这样的代码:

public class Test {
    public static void test(List persons) {
        Map map = new HashMap<>();

        //把name相同的person合并,age相加
        for (Person person : persons) {
            if(map.containsKey(person.getName())) {
                Person person1 = map.get(person.getName());
                person1.setAge(person.getAge() + person1.getAge());
            } else {
                map.put(person.getName(),person);
            }
        }
        Collection values = map.values();
        //这个persons指向新new的一个对象
        persons = new ArrayList<>(values);
        System.out.println(persons.toString());//-->[Person{name='s1', age='8'}]
    }

    public static void main(String[] args){
        ArrayList persons = new ArrayList<>();
        persons.add(new Person("s1",5));
        persons.add(new Person("s1",3));

        test(persons);

        System.out.println(persons);//-->[Person{name='s1', age='8'}, Person{name='s1', age='3'}]
    }

}
  • main函数中外部有一个persons对象,传入test函数中,test函数中又把persons指向了一个新的对象,for循环中直接操作了persons中的对象。看下代码中的输出,persons的打印方法内外不一样。

下面的例子清晰点:

public class Test2 {
 
    public static void setValue(String str){
        str = "ss";
    }
    public static void setValue(Man str){
        str = new Man("test");
    }
 
    public static class Man{
        private String name;
 
        public String getName() {
            return name;
        }
 
        public void setName(String name) {
            this.name = name;
        }
 
        public Man(String name) {
            this.name = name;
        }
 
        @Override
        public String toString() {
            return "Man{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
 
    public static void main(String[] args) {
 
        String str = "s";
        setValue(str);
 
        System.out.println(str);
 
 
        Man man = null;
        setValue(man);
        System.out.println(man);
 
    }
}

上面代码输出:

s
null

原因是方法在执行的时候有栈帧的概念,入栈的时候只是压栈,方法参数是传入参数的副本。

基本类型:值存放在局部变量表中,无论如何修改只会修改当前栈帧的值,方法执行结束对方法外不会做任何改变;此时需要改变外层的变量,必须返回主动赋值。

引用数据类型:指针存放在局部变量表中,调用方法的时候,副本引用压栈,赋值仅改变副本的引用。但是如果直接改变副本引用的值,修改了引用地址的对象,此时方法以外的引用此地址对象当然被修改。(两个引用,同一个地址,任何修改行为2个引用同时生效)

比如

public static void setValue(StringBuilder str){
        str = new StringBuilder("sss");
    }
    
    public static void setValue2(StringBuilder str){
        str.append("sss");
    }
 
 
    public static void main(String[] args) {
 
        StringBuilder str = new StringBuilder();
        setValue(str);
 
        System.out.println(str.toString()); //输出空字符串
 
 
        setValue2(str);
        System.out.println(str.toString()); //输出sss
 
    }

关于String,本质是final类型char数组,不可修改,只能赋值,在做参数传入方法修改时,其实是新建对象,必须返回重新对外面的变量赋值才会对外面的String引用生效。

原文链接:https://blog.csdn.net/fenglllle/article/details/81389286

你可能感兴趣的:(Java 变量参数传入方法,修改后是否影响外面的值)