当前位置:编程学习 > JAVA >>

问一个比较纠结的基础问题,

String s1 = "a";
String s2 = s1;
s1 = "b";
System.out.println(s2);

为什么输出a? --------------------编程问答-------------------- --------------------编程问答-------------------- 这个问题确实很纠结....
我纠结着要怎么给你解释你才能看明白...
楼主是不是之前学过C++啊,才不明白为什么的?
这个问题很好理解吧... --------------------编程问答-------------------- String s1 = "a";
String s2 = s1;
s2 = "b";
System.out.println(s1); 也是a --------------------编程问答-------------------- 好纠结的啊。 --------------------编程问答--------------------
引用 2 楼 duanwu2330323 的回复:
这个问题确实很纠结....
我纠结着要怎么给你解释你才能看明白...
楼主是不是之前学过C++啊,才不明白为什么的?
这个问题很好理解吧...
没有, 刚刚没事琢磨了一下,越想越不对啊,求大神解答 --------------------编程问答--------------------
引用 4 楼 rui888 的回复:
好纠结的啊。
就是啊。 --------------------编程问答-------------------- String s1 = "a";//这里的s1的值就是"a"了
String s2 = s1;  //这句话是说吧s1的值赋给s2,也就是说s2的值也是"a"了

然后你打印s2,不是"a"  还能是什么? --------------------编程问答--------------------
引用 7 楼 duanwu2330323 的回复:
String s1 = "a";//这里的s1的值就是"a"了
String s2 = s1;  //这句话是说吧s1的值赋给s2,也就是说s2的值也是"a"了

然后你打印s2,不是"a"  还能是什么?
不是说他们的内存地址是一样的吗?S2=S1 这是只是把内存中的地址给了s2, --------------------编程问答--------------------
引用 8 楼 yu929927571 的回复:
Quote: 引用 7 楼 duanwu2330323 的回复:

String s1 = "a";//这里的s1的值就是"a"了
String s2 = s1;  //这句话是说吧s1的值赋给s2,也就是说s2的值也是"a"了

然后你打印s2,不是"a"  还能是什么?
不是说他们的内存地址是一样的吗?S2=S1 这是只是把内存中的地址给了s2,


所以我才怀疑楼主是不是搞C++的 --------------------编程问答-------------------- s2 本来就给给它赋的 a,为什么不是a?
s1 重新赋值了肯定就是 b 啊,怎么会输出a --------------------编程问答--------------------
引用 9 楼 duanwu2330323 的回复:
Quote: 引用 8 楼 yu929927571 的回复:

Quote: 引用 7 楼 duanwu2330323 的回复:

String s1 = "a";//这里的s1的值就是"a"了
String s2 = s1;  //这句话是说吧s1的值赋给s2,也就是说s2的值也是"a"了

然后你打印s2,不是"a"  还能是什么?
不是说他们的内存地址是一样的吗?S2=S1 这是只是把内存中的地址给了s2,


所以我才怀疑楼主是不是搞C++的
--------------------编程问答-------------------- 值传递  木有指针。。。
--------------------编程问答--------------------
引用 楼主 yu929927571 的回复:
String s1 = "a";
String s2 = s1;
s1 = "b";
System.out.println(s2);

为什么输出a?


这样赋值的话  当int来看 不知道这样说正确否 --------------------编程问答-------------------- 刚刚看了篇文章感觉是这样 , 你们觉得对不对?

String 类是final修饰的,也就是说当我把s1重新赋值的时候s1在内存中的地址就变了?? --------------------编程问答--------------------
引用 13 楼 songbgi 的回复:
Quote: 引用 楼主 yu929927571 的回复:

String s1 = "a";
String s2 = s1;
s1 = "b";
System.out.println(s2);

为什么输出a?


这样赋值的话  当int来看 不知道这样说正确否
好像是吧?我基础不行啊。 --------------------编程问答--------------------
Quote: 引用 12 楼 u011559804 的回复:

值传递  木有指针。。。
没懂,大神详解 --------------------编程问答-------------------- 这个想了一下可以这样理解:
首先String s1 = "a";是将"a"放入字符串驻留池同时指向"a"的引用,String s2是指向字符串驻留池的"a"引用,而不是s1的内存地址;
当s1 = "b";是将"b"放入字符串驻留池同时指向"b"的引用,而这时s2还是指向字符串驻留池的"a"引用。
--------------------编程问答-------------------- s1="b";
为 s1 变量 重新赋值!
就和 String s1 = "a"; 一个意思
s2=s1 是
赋值! 将 s1 指向的内存地址穿过去了。
。s2 不是依赖s1.
而是直接指向了"a" 的内存地址。
传递的是引用。 --------------------编程问答-------------------- 楼主看看String 和StringBuffer区别就立马明白了为什么是这样子的。。求分 --------------------编程问答-------------------- 栈中先建一个引用对象s1,指向一个内存地址,这个地址的值为a
然后再建一个引用对象s2, 指向s1的引用,也就是s1指向的内存地址,也就是a
s1 和 s2 共同指向了一个具体的内存地址。
这时,将s1 指向的地址的值改为b
那么他们指向同一个地址,s2也就是b了。 --------------------编程问答-------------------- 当后面s1="b"时,改变的只是s1的地址,但是没有改变s2的地址,所以这时候的s1与s2的地址是不一样的,如果你在s2=s1,s2的值就是b了 --------------------编程问答-------------------- 楼主看看这个吧,看完应该就理解了 堆栈 --------------------编程问答--------------------
String s1 = "a";
String s2 = s1;
s1 = "b";
System.out.println(s2);

不知道楼主学的是什么语言;我学的是java;就从Java方面解释下,首先java里的字符类有个常量池的概念,如果常量池没有“a”这个字符的话就创建这个对象同时在堆里创建一个引用对象s1,并且把字符a放入常量池里。
第二行代码是把s1在堆中的内存地址赋值给s2,此时s2的内存地址指向的就是常量池中的“a”.第3行代码中的字符“b”和字符“a”一样的创建方式,并且在堆中分配新的物理内存地址给s1,此时的字符“b”的引用对象s1所指向的内存地址已经和前面的内存地址不同了。所以打印s2自然会打印s2内存地址所对应的值“a”. --------------------编程问答--------------------
引用 23 楼 zhzwsjc1000 的回复:
String s1 = "a";
String s2 = s1;
s1 = "b";
System.out.println(s2);

不知道楼主学的是什么语言;我学的是java;就从Java方面解释下,首先java里的字符类有个常量池的概念,如果常量池没有“a”这个字符的话就创建这个对象同时在堆里创建一个引用对象s1,并且把字符a放入常量池里。
第二行代码是把s1在堆中的内存地址赋值给s2,此时s2的内存地址指向的就是常量池中的“a”.第3行代码中的字符“b”和字符“a”一样的创建方式,并且在堆中分配新的物理内存地址给s1,此时的字符“b”的引用对象s1所指向的内存地址已经和前面的内存地址不同了。所以打印s2自然会打印s2内存地址所对应的值“a”.

恩 是这样子的 楼主 --------------------编程问答-------------------- 学C的  不太明白  路过......... --------------------编程问答-------------------- 这是"写入时拷贝" COpyOnWrite   --------------------编程问答-------------------- String是被final修饰的 --------------------编程问答-------------------- 用C的理解方式解释下,不知道对不对。
char *s1 = "a";
char *s2 = s1;
s1 = "b";
printf("%s", s2);
printf("%s", s1);

s1,s2作为局部变量放在堆栈区,字符串a,b放在只读段。
s1,s2仅仅是变量而已,所谓指针,也只是一个指针类型的变量。

第一行,s1指向字符串a的内存地址,
第二行,s1把地址值赋值给s2,S2也指向字符串a
第三行,s1指向字符串b的内存地址
第四行,打印S2,当然打印的是字符串a了
第五行,打印S1,当然打印的是字符串b了

下面是我用的C#写的测试代码,现在没搞C了。 --------------------编程问答--------------------     class Program
    {
        static void Main(string[] args)
        {
            string s1 = "a";
            string s2 = s1;
            s1 = "b";
            Console.Write("s2 = "s2);
            Console.Write("s1 = "s1);
            Console.Read();
        }

输出结果s2 = a, s1 = b. --------------------编程问答-------------------- String s1 = "a"; // s1引用"a"对象
String s2 = s1; // s2引用s1引用的对象,即,s2引用"a"对象
s1 = "b"; // s1现在引用"b"对象(但是s2没有变化对吧)
System.out.println(s2); // s2还是引用"a"对象,打出a

// 如果“引用”这个词还不好理解,请把它改成“指向”,并在纸上画出这种指向的关系。

String s1 = "a"; // s1指向"a"对象
String s2 = s1; // s2指向s1指向的对象,即,s2指向"a"对象
s1 = "b"; // s1现在指向"b"对象(但是s2没有变化对吧)
System.out.println(s2); // s2还是指向"a"对象,打出a

String s1 = "a"; // s1 -> "a"
String s2 = s1; // s2 -> "a" <- s1,注意,不是s2 -> s1 -> "a"
s1 = "b"; // s2 -> "a" s1 -> "b"
System.out.println(s2); // so ...

个人觉得问题的关键就是“如何解读=操作”。
--------------------编程问答--------------------
引用 3 楼 yu929927571 的回复:
String s1 = "a";
String s2 = s1;
s2 = "b";
System.out.println(s1); 也是a


这有啥好纠结的  
第一句:把"a"在内存中的地址给赋值给s1
第二句:把"a"在内存中的地址复制一份给s2,也就是此时s1、s2均指向内存中的"a"
第三句:把"b"在内存中的地址赋值给s2,此时s2指向内存中的"b",而s1还是指向内存中的"a"
所以打印出a --------------------编程问答-------------------- 你这个是先已经给s2赋过值了啊   要是将s1 = "b";放在上面写 输出的是b --------------------编程问答--------------------
引用 3 楼 yu929927571 的回复:
String s1 = "a";
String s2 = s1;
s2 = "b";
System.out.println(s1); 也是a


你先要弄清楚是哪个给哪个赋值的   右边的值给左边的对象赋值 --------------------编程问答-------------------- 由于String是immutable的,为了便于理解,我使用如下代码片段进行对比(int[]是mutable的)
        int[] a = { 1, 2, 3, }; // a引用一个int[]对象,该对象为一个int array,三个元素1,2,3
        int[] b = a; // b引用a引用的那个对象,同一个对象
        b[0] = 0; // 修改b引用的那个对象(也就是修改了a引用的对象,是同一个对象来着)
        for (int i : a) {
            System.out.println(i); // a引用的对象变了,0,2,3
        }
--------------------编程问答-------------------- 楼主内存操作理解不够。学好C还是很有必要的。 --------------------编程问答-------------------- ............................
............
String是字胡窜的意思! --------------------编程问答-------------------- String s1 = "a";
String s2 = s1;
s1 = "b";
System.out.println(s2);

为什么输出a? 

对象变量s1->对象值a
对象变量s2->对象变量s1->对象值a 实际上 对象变量s2->对象值a
对象变量s1->对象值b
。。。。。。。
在这里如果对象变量s2->对象变量s1
那么 对象变量s2->对象变量s1->对象值b   s2=b
。。。。。
没有 那么。。。。
s2=a
s1=b
--------------------编程问答--------------------
引用 楼主 yu929927571 的回复:
String s1 = "a";
String s2 = s1;
s1 = "b";
System.out.println(s2);

为什么输出a?


楼主跟你画个图 你就明白了
首先:


然后是值传递  即s1把自己保存的内存地址复制一份给了s2


然后s1再次赋值 把自己原来保存的"a"的内存地址换成了"b"的内存地址


而s2保存的还是"a"的内存地址 
所以输出s2是"a" --------------------编程问答-------------------- 加个断点你就懂了 --------------------编程问答-------------------- 神贴... --------------------编程问答-------------------- 一步步看执行顺序。。s2的值在第二句就定了,后面又没改过。。 --------------------编程问答-------------------- 输出"a",没有问题啊 --------------------编程问答--------------------
引用 2 楼 duanwu2330323 的回复:
这个问题确实很纠结....
我纠结着要怎么给你解释你才能看明白...
楼主是不是之前学过C++啊,才不明白为什么的?
这个问题很好理解吧...

这跟C++有什么关系?C++要是这么写,结果也是一样的。 --------------------编程问答--------------------
引用 24 楼 guanweiliang 的回复:
Quote: 引用 23 楼 zhzwsjc1000 的回复:

String s1 = "a";
String s2 = s1;
s1 = "b";
System.out.println(s2);

不知道楼主学的是什么语言;我学的是java;就从Java方面解释下,首先java里的字符类有个常量池的概念,如果常量池没有“a”这个字符的话就创建这个对象同时在堆里创建一个引用对象s1,并且把字符a放入常量池里。
第二行代码是把s1在堆中的内存地址赋值给s2,此时s2的内存地址指向的就是常量池中的“a”.第3行代码中的字符“b”和字符“a”一样的创建方式,并且在堆中分配新的物理内存地址给s1,此时的字符“b”的引用对象s1所指向的内存地址已经和前面的内存地址不同了。所以打印s2自然会打印s2内存地址所对应的值“a”.

恩 是这样子的 楼主

String s1 = "a";会牵扯到堆的概念吗,只会停留在栈上面吧。
String s1 = "a"存放在常量池,常量池放在栈中,s1直接指向常量池的这块引用;
如果String s1 = new String("a");才会牵扯到堆,在常量池创建“a”的同时在堆中开辟一块内存,这时才是s1指向堆中的内存地址,堆中的内存地址指向常量池中的"a"引用。 --------------------编程问答-------------------- --------------------编程问答-------------------- String s1 = "a";(1)
String s2 = s1;(2)
s1 = "b";(3)
(1)行    s1是地址 在栈中,a是内容在内存中(堆),s1指向a
(2)行   s2是地址 在栈中,s2=s1   s1的地址赋给s2,就是说s2也指向了a
(3)行   s1=“b”,s1指向了b
三句话执行下来,s2指向的是a  所以输出a。
过程中s1只是指向的内容变了而已。 --------------------编程问答-------------------- 这个,有点基础了。我看都回答出来了。 --------------------编程问答-------------------- 除 --------------------编程问答-------------------- 除 --------------------编程问答-------------------- 定义一个变量必须初始化后才能使用,初始化可以new一个新的对象,也可以将这个变量指向一个已经存在的变量。变量不是包含一个对象,只是引用一个对象。
变量是一个指向对象的指针,一个对象包含另一个对象也是包含这个对象的指针。java 中如果这个指针没有初始化,会报错不会产生一个随机的结果。

String s1 = "a"; //这是s1指向一个匿名对象“a”
String s2 = s1;// 这里s2也指向这个匿名对象“a”,而不是指向S1
s1 = "b";  这时候s1又指向匿名对象“B”, 而S2还是指向匿名对象“a”
System.out.println(s2);

java 中问什么会有普通克隆和深层 克隆的区别。

普通的克隆只是给变量的分配了内存空间,对象里变量和原来的对象指向相同。
深层 就是对象里变量也是新的
--------------------编程问答--------------------
引用 44 楼 u011213572 的回复:
Quote: 引用 24 楼 guanweiliang 的回复:

Quote: 引用 23 楼 zhzwsjc1000 的回复:

String s1 = "a";
String s2 = s1;
s1 = "b";
System.out.println(s2);

不知道楼主学的是什么语言;我学的是java;就从Java方面解释下,首先java里的字符类有个常量池的概念,如果常量池没有“a”这个字符的话就创建这个对象同时在堆里创建一个引用对象s1,并且把字符a放入常量池里。
第二行代码是把s1在堆中的内存地址赋值给s2,此时s2的内存地址指向的就是常量池中的“a”.第3行代码中的字符“b”和字符“a”一样的创建方式,并且在堆中分配新的物理内存地址给s1,此时的字符“b”的引用对象s1所指向的内存地址已经和前面的内存地址不同了。所以打印s2自然会打印s2内存地址所对应的值“a”.

恩 是这样子的 楼主

String s1 = "a";会牵扯到堆的概念吗,只会停留在栈上面吧。
String s1 = "a"存放在常量池,常量池放在栈中,s1直接指向常量池的这块引用;
如果String s1 = new String("a");才会牵扯到堆,在常量池创建“a”的同时在堆中开辟一块内存,这时才是s1指向堆中的内存地址,堆中的内存地址指向常量池中的"a"引用。


百度了一会,你讲的对的 String s1 = "a";确实不会牵扯到堆的概念。 呵呵菜鸟菜鸟 --------------------编程问答-------------------- 我家有一只小狗a,我给它取了个名字叫s1,一天把小狗a送给了邻居,邻居又给它取了个名字叫s2,然后我又买了一只小狗b,我还是给它取名字叫s1。 --------------------编程问答-------------------- 该结贴了! --------------------编程问答-------------------- 从Java上说:
String str1 = "a";其实就是String str1 = new String("a");是在堆内存中新建一个空间,存放一个字符串
String str2 = str1;此时栈内存中str2对象所指向的也是字符串“a”;
同样:
str1 = "b";其实就是str1 = new String("b");在堆内存中又开辟另一个新的空间,存入字符串“b”,但是str2对象所指的堆内存空间还是以前“a”所在的空间,所以输出结果是显示“a” --------------------编程问答-------------------- 大约意思是这样的--------求轻拍:



String a = "aa";
String b = a;
a = "tt";
System.out.println(b);


①为“aa”划分内存
②让a指向"aa"的内存单元
③让b指向a指向的内存单元也就是"aa"
④新建内存单元"tt"
⑤让a指向"tt"的内存单元
补充:Java ,  Java EE
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,