黑马程序员技术交流社区

标题: 关于比较两个变量的疑问 [打印本页]

作者: FFF    时间: 2013-10-3 11:12
标题: 关于比较两个变量的疑问
本帖最后由 FFF 于 2013-10-3 13:41 编辑

  1. public class temp10_03 {

  2. public static void main(String[] args){
  3. String s0 = "kvill";
  4. String s1 = "kvill";
  5. String s2 = "kv"+"ill";

  6. int i0 = 01 ;
  7. int i1 = 01 ;
  8. int i2 = 0+1;

  9. System.out.println( s0 == s1 );
  10. System.out.println( s0 == s2 );

  11. System.out.println( i0 == i1 );
  12. System.out.println( i0 == i2 );
  13. }
  14. }
复制代码
为什么输出结果都是True呢?不是说比较的时候是比较两个变量的内存地址吗?为什么都是一样的?

作者: Simple_love    时间: 2013-10-3 11:29
本帖最后由 Simple_love 于 2013-10-3 11:31 编辑

你之所以为true, 是因为s1 s2 类类型的变量指向了同一个对象"kvill", i0、i1同样也是类类型的变量指定了同一个对象01, 由于双等号是比较对象是否相同, 所有运行的结果都为true
作者: 陈钦涛    时间: 2013-10-3 11:34
String s0 = "kvill"时, 栈内存的变量s0指向了常量池中的“kvill”(常量池没有kvill的话就会被创建),String s1 = "kvill"时,s1和s0指向的都是常量池的“kvill”,String s2 = "kv"+"ill"时,创建了三个对象,“kv”和“ill“,但是没有创建”kvill“,因为之前已经创建了,它们都是同一份的”kvill“,所以s2指向的也是s0和s1一样的地址。下面int类型的比较,道理同String类型的比较,不过它们是储存在栈内存中,同样是栈内存中已经有了的话,就不会再开辟新的内存空间。希望能帮到你。
作者: ←佐手邊の永远    时间: 2013-10-3 11:39
关于字符串的创建有两种方式,
1.String s = "abc";//这个用双引号引起来的直接会将abc放入常量池中,如果你在写一个String s1 = "abc";则s2会直接指向常量池中的abc,不会在新创建一个
2.String s2= new String("abc");//这个则是创建了两个对象,一个是new出来的,在堆中,一个是在常量池中
如果你这样比较
  1. public class temp10_03 {

  2. public static void main(String[] args){
  3. String s0 = new String("kivll");
  4. String s1 = new String("kvill");
  5. String s2 = "kv"+"ill";

  6. int i0 = 01 ;
  7. int i1 = 01 ;
  8. int i2 = 0+1;

  9. System.out.println( s0 == s1 );
  10. System.out.println( s0 == s2 );

  11. System.out.println( i0 == i1 );
  12. System.out.println( i0 == i2 );
  13. }
  14. }
复制代码
肯定是false

int i0 = 01 ;
int i1 = 01 ;
int i2 = 0+1;//你这是在比较01是不是等于01,也是true,这个没比较对象


作者: ←佐手邊の永远    时间: 2013-10-3 11:43
陈钦涛 发表于 2013-10-3 11:34
String s0 = "kvill"时, 栈内存的变量s0指向了常量池中的“kvill”(常量池没有kvill的话就会被创建),Stri ...

int类型是基本数据类型,String是一直特殊的引用数据类型,我认为他俩应该不太一样吧,
作者: 路边小色狼    时间: 2013-10-3 11:53
关于==,再给你举个例子:因为一般==会和equals来比较。
Integer i1=new Integer(2);
Integer i2=new Integer(2);
i1==i2      这就是false
i1.equals(i2)   这是true;
-----------------------------------------------------------------------
总结,你可以不去理会到底有没有在堆内存中有没有开辟新空间,可以这样理解:
    如果比的是变量,那只能用==,不能用equals    ,这时==比的是堆内存中的值。因为在堆内存中,值一样确实是不开辟新空间,所以地址也是一样的。
    如果比的是对象,那==比的时,比的是地址。 用equals比的则是值,理由同上。
而你举的例子全是变量,比的是堆内存中的指向的值。
作者: 陈钦涛    时间: 2013-10-3 11:54
←佐手邊の永远 发表于 2013-10-3 11:43
int类型是基本数据类型,String是一直特殊的引用数据类型,我认为他俩应该不太一样吧, ...

我说的是基本数据类型在栈内存和引用数据类型在栈内存和常量池的创建方式类似,当然==比较基本数据类型的时候是比较它们的值,引用数据类型比较的是它们的内存地址。

作者: 周志龙    时间: 2013-10-3 11:54
String s2= new String("abc");创建了3个,栈 堆 常量池
作者: ←佐手邊の永远    时间: 2013-10-3 11:57
陈钦涛 发表于 2013-10-3 11:54
我说的是基本数据类型在栈内存和引用数据类型在栈内存和常量池的创建方式类似,当然==比较基本数据类型的 ...

懂了。。。。。。{:soso_e100:}

作者: qq316525598    时间: 2013-10-3 12:14

                String s0 = "kvill";
                String s1 = "kvill";
                String s2 = "kv" + "ill";

                int i0 = 01;
                int i1 = 01;
                int i2 = 0 + 1;

                System.out.println(s0 == s1);  //String因为是引用类型,这类变量声明时不会分配内存,只是存储了一个内存地址,想具体知道看看数据结构就好了。s0的引用地址是"kvill",s1的引用地址也是"kvill",包括s2也是相同的引用地址所以是true
                System.out.println(s0 == s2);

                System.out.println(i0 == i1);//你的数字值都是1 肯定是等于的
                System.out.println(i0 == i2);
作者: 空杯    时间: 2013-10-3 13:56
{:soso_e110:}
作者: 麦子    时间: 2013-10-3 19:09
本帖最后由 麦子 于 2013-10-3 19:14 编辑

哥么,给你说个大白话吧
String s0 = new String("kivll");
String s1 = new String("kvill");
String s2 = "kv"+"ill";
s0==s1这个为true不用我讲吧,为什么s0==s2也为true,那是因为它先完成了你的字符串相加才赋的值
,那s2肯定也是kvill啊!
我大概知道你想说的是什么
String s2 = "kv";
String s3 = "ill";
String s4 = s2+s3;
System.out.println( s0 == s1 );
System.out.println( s0 == s4 );
此时,s4在堆内存中的只和s2就不一样了
以上代码就是你要的结果了
要想比较字符串的内容,应该使用该对象的方法equals();
int i0 = 01 ;
int i1 = 01 ;
int i2 = 0+1;
至于以上代码,因为都是简单的基本数据类型,比较的就是它的值







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