黑马程序员技术交流社区

标题: 值传递和引用传递中String到底是什么传递? [打印本页]

作者: 大自然的搬运工    时间: 2015-10-27 20:55
标题: 值传递和引用传递中String到底是什么传递?
值传递和引用传递中String到底是什么传递
String可以new对象,理论上应该是地址传递,为什么调用方法里的值改变了而调用者里的值没有变??
求大神给解释一下?

public class Test0001 {

        public static void main(String[] args) {

                // 值传递,方法内改变,外边不变
                int x = 5;
                adds(5);
                System.out.println(x);
                // 引用传递,方法改变引用中的值,都改变
                Man m = new Man("小明");
                adds(m);
                System.out.println(m.getName());
               
                String str = new String("jshak");
                adds(str);         //函数里的形参s=jshakaaaaaaaaaaaa
                System.out.println(str);    //为什么没改变?str = "jshak"
        }
       
        private static void adds(Man p) {
                //改变姓名
                p.setName("大明");
                System.out.println(p.getName());

        }

        private static void adds(int i) {
                //改变值
                i = i + 10;
                System.out.println(i);
        }

        private static void adds(String s) {
                //改变??
                s = s + "aaaaaaaaaaaa";
                System.out.println(s);
        }

}

class Man {
        private String name;

        public Man(String name) {
                super();
                this.name = name;
        }

        public String getName() {
                return name;
        }

        public void setName(String name) {
                this.name = name;
        }

}



作者: cool257    时间: 2015-10-27 20:55
本帖最后由 cool257 于 2015-10-27 23:43 编辑

这个问题的根本在于:在方法内部,无法改变方法外部变量的引用地址!
比如申明一个变量 String str="a";这句话的意思是我们把str 的引用,指向了 "a“这个对象;然后我们进行以下操作 str="b";这个时候我们是改变了引用指向的对象,让str指向了"b",原来的"a"对象并没有被改变;
我举个例子:你们班有个人叫”张三“, 有个叫”李四“,然后老师做了一件事Person  班长 = ”张三“;
现在张三是班长了,同学问老师,我们要找班长,老师就说:去找” 张三“! 过段时间,老师觉得张三能力不行,就换个人:Person 班长=”李四“;假如这个时候要找班长,老师就会叫我们去找”李四“!因为班长的指向对象改变了!但是切记一件事,班长只是指向的对象换了,”张三“还是那个”张三“,
然后我们说你的问题:
比如在方法外部创建了一个Man对象, 语句为Man man=new Man("张三");
然后你写了个方法public void adds(Man man) {
   man =new Man("李四");
System.out.println(man.getName());
}
调用方法时会打印 “李四”,但是在方法外再次调用man的名字,名字依然是"张三"..
这个就是你问题的答案了,因为在方法内部不能改变引用地址,所以出了方法就无效了!
在方法内部我们做的哪些事情能够生效呢?改变所传参数引用对象的属性!虽然我们无法改变参数的引用,但是我们可以在方法内部改变引用对象的属性,比如在上面所提方法中我们可以使用man.setName()方法来改变所传参数的name属性,这个改变是对象的属性,所以是永久生效的,打比方,老师没换班长,但是”张三“改名叫”赵六“,所以以后找班长,就是找”赵六“这个人了,因为”张三“的名字改成了”赵六“,对象没变,只是对象的属性发生了改变!String类的对象是无法改变的,即使以后使用了String的各种方法,获得的也是新的对象,这个知识你目前应该还没学到吧?老师以后说String类的时候会反复讲这个东西的.
如果觉得回答满意,请给分..压力刷币中.
作者: swkfx    时间: 2015-10-27 22:29
private static void adds(int i) {
                //改变值
                i = i + 10;
                System.out.println(i);
        }
这个没有返回值类型。你把5传进来 这里的i= 15  按你这个语句输出。

// 值传递,方法内改变,外边不变
                int x = 5;
                adds(5);
                System.out.println(x);
主函数里的运行 只有你赋值x=5  输出5  而中间的adds(5) 会执行,但是不会对x的值改变,因为你传的不是x 而是5 .相当于在adds的方法中 你赋值 i= 5 而不是 i=x; 即便你赋值 i= x   ; 因为你的方法是void 无返回值类型的,在这个方法局部内,值做了改变,但是你System.out.println(x)是主函数局部中的变量x。跟adds(x) 没有关系。如果想改变值,要把x定义成 成员变量   并将你的方法更改返回值类型为int 如下代码.如果你都不改想看到x值的改变 只能是输出  在adds方法中的改变.即  System.out.println(adds(x));
这是我的理解,如果有误还请各位指出,谢谢.
  1. public class Test {

  2.         static int x = 5;

  3.         public static void main(String[] args) {
  4.                 x = adds(x);
  5.                 System.out.println(x);

  6.         }

  7.         private static int adds(int x) {
  8.                 x = x + 10;
  9.                 return x;
  10.         }

  11. }
复制代码




作者: 大自然的搬运工    时间: 2015-10-27 22:41
swkfx 发表于 2015-10-27 22:29
private static void adds(int i) {
                //改变值
                i = i + 10;

谢谢,我知道你说的这个,基本数据类型是值传递,函数里的改变了,主函数里的肯定不变,这个我理解。我想说的是Man 和 String  都是往函数里传的引用地址,为什么 String 的主函数值没有变?(Man的改变属于引用传递我也理解的)。
作者: swkfx    时间: 2015-10-27 23:01
Man 你有实例对象,就是说这个m 在内存中了.然后你调用方法改变了内存中m对象的name值.
而你的String str 在主函数中是局部变量.main中str = "jshak"
而你再调用改变str的方法  
private static void adds(String str) { // String str = new String"jshak";
                str = str + "aaaaaaaaaaaa";
                System.out.println("method:" + str);
        }
方法中的str 是改变的 你的输出一句中可以加上个区别来看 方法中是打印的.
但是方法中改变的是方法中的局部变量 str 跟主函数中的str没有什么关系啊.
或者 你可以不要写成String str  你可以写成 String s
也就是说 你的方法中改变了s的值 而主函数中的str 并没有对其做什么操作啊.
跟你上面的 int 类型是一个情况啊. 你调用了方法,但是方法只是对方法内的局部变量做了变更.
主函数中的 局部变量 只是因为你起了相同的局部变量名 ,但是他们并不是同一个变量.
作者: 大自然的搬运工    时间: 2015-10-27 23:35
swkfx 发表于 2015-10-27 23:01
Man 你有实例对象,就是说这个m 在内存中了.然后你调用方法改变了内存中m对象的name值.
而你的String str 在 ...

String str = new String ();
这句话不是在堆内创建一个对象吗?他难道不是把堆里String对象的地址值传进去了吗?
   int   x   在栈里存的是值,
String str 在栈里边存的是他在堆里的地址值;
Man   m  在栈里也是存的他在堆里的地址值;
String 为什么和Man 不同。
作者: Mona33    时间: 2015-10-27 23:54
因为String类重写了toString()方法,输出时对象后面默认有.toString()
作者: 大自然的搬运工    时间: 2015-10-28 00:03
cool257 发表于 2015-10-27 23:40
这个问题的根本在于:在方法内部,无法改变方法外部变量的引用地址!
比如申明一个变量 String str="a";这 ...

感谢你写这么多耐心的回答我的疑问 ,,,现在想明白了。。。。十币送上。
作者: 大自然的搬运工    时间: 2015-10-28 00:08
Mona33 发表于 2015-10-27 23:54
因为String类重写了toString()方法,输出时对象后面默认有.toString()

这个toString方法和引用传递还有关系呢吗?   能不能简单的说一说什么关系?
作者: cool257    时间: 2015-10-28 00:24
谢了,toString()方法是Object类的方法,所有类都直接或者间接继承了Object类,java中有的类将此方法重写了.......如果没有重写这个方法,使用语句System.out.println(变量名称),是打印的这个变量使用toString()方法的返回值”String类型的“.没有重写toString方法的话,toString方法返回的是”对象的类名+@+hashCode()方法返回的值“,你可以试试打印你自己定义类的对象,应该是这个形式的...说太多也不利于消化,有关继承和Object类,在面向对象章节会讲解的.八种基本数据类型使用System.out.println();输出的结果都是数值。String类是重写了toString方法,不过和你的问题没关系.
作者: 雨来    时间: 2015-10-28 11:42
忘记了,之前可以理解的
作者: 大自然的搬运工    时间: 2015-10-28 17:08
雨来 发表于 2015-10-28 11:42
忘记了,之前可以理解的

上面兄弟说的挺清楚的了,你可以和看看,巩固一下吧,,共勉
作者: 菊花爆满山    时间: 2015-10-28 23:30
字符串最大特点: 一旦被初始化 就不可以被改变
作者: 大自然的搬运工    时间: 2015-10-29 16:16
菊花爆满山 发表于 2015-10-28 23:30
字符串最大特点: 一旦被初始化 就不可以被改变

我知道这个
作者: _let'sgo    时间: 2015-10-30 11:00
简单来说,String类对象一旦被赋值就不能被改变




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2