今天看javacsript 想起了原来一个关于java的一个String 的问题
在javascript中var s1="hello";
var s2="hell"+"o";
alert(s1==s2)
结果应该是true原因是字符串按照值进行比较
那么在java中同样的代码public static void main(String[] args) {
String a="hello";
String b="hell"+"o";
System.out.println(a==b);
}
结果也是true改怎么解释呢

解决方案 »

  1.   

    此回复为自动发出,仅用于显示而已,并无任何其他特殊作用
    楼主【zidasine】截止到2008-07-01 15:08:01的历史汇总数据(不包括此帖):
    发帖数:11                 发帖分:776                
    结贴数:11                 结贴分:776                
    未结数:0                  未结分:0                  
    结贴率:100.00%            结分率:100.00%            
    敬礼!
      

  2.   

    这个问题你要了解java的储存机制。应该很好理解,
    public static void main(String[] args) {
            String a="hello";
            String b=new String("hello");
            System.out.println(a==b);
    }
    这样的结果就是false
      

  3.   

    Java字符串类(java.lang.String)是Java中使用最多的类,也是最为特殊的一个类,很多时候,我们对它既熟悉又陌生。
     
    一、从根本上认识java.lang.String类和String池
     
    首先,我建议先看看String类的源码实现,这是从本质上认识String类的根本出发点。从中可以看到:
    1、String类是final的,不可被继承。public final class String。
    2、String类是的本质是字符数组char[], 并且其值不可改变。private final char value[];
    然后打开String类的API文档,可以发现:
    3、String类对象有个特殊的创建的方式,就是直接指定比如String x = "abc","abc"就表示一个字符串对象。而x是"abc"对象的地址,也叫做"abc"对象的引用。
    4、String对象可以通过“+”串联。串联后会生成新的字符串。也可以通过concat()来串联,这个后面会讲述。
    6、Java运行时会维护一个String Pool(String池),JavaDoc翻译很模糊“字符串缓冲区”。String池用来存放运行时中产生的各种字符串,并且池中的字符串的内容不重复。而一般对象不存在这个缓冲池,并且创建的对象仅仅存在于方法的堆栈区。下面是个系统内存示意图: 
    5、创建字符串的方式很多,归纳起来有三类:
    其一,使用new关键字创建字符串,比如String s1 = new String("abc");
    其二,直接指定。比如String s2 = "abc";
    其三,使用串联生成新的字符串。比如String s3 = "ab" + "c"; 
     
    二、String对象的创建
     
    String对象的创建也很讲究,关键是要明白其原理。
    原理1:当使用任何方式来创建一个字符串对象s时,Java运行时(运行中JVM)会拿着这个X在String池中找是否存在内容相同的字符串对象,如果不存在,则在池中创建一个字符串s,否则,不在池中添加。
     
    原理2:Java中,只要使用new关键字来创建对象,则一定会(在堆区或栈区)创建一个新的对象。
     
    原理3:使用直接指定或者使用纯字符串串联来创建String对象,则仅仅会检查维护String池中的字符串,池中没有就在池中创建一个,有则罢了!但绝不会在堆栈区再去创建该String对象。
     
    原理4:使用包含变量的表达式来创建String对象,则不仅会检查维护String池,而且还会在堆栈区创建一个String对象。
     
    另外,String的intern()方法是一个本地方法,定义为public native String intern(); intern()方法的价值在于让开发者能将注意力集中到String池上。当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。 引自他处!
      

  4.   

    String b="hell"+"o";
    java是编译型语言,在编译器进行了优化
    其实这个就等于String b = "hello";
    你试一试
    String c = "o";
    String b = "hell" + c;
    结果就为False
      

  5.   

    String 是类,不是基本数据类型。。用==对于对象来说是比较首地址,两个String对象==的结果肯定是False。
    对象判断相等是用基类Object中equals方法。
      

  6.   

    因为他们都是常量池里的同一个对象,
    所以地址相同,当然就是true
      

  7.   

    String a = "Hello";
    String b = "Hell"+"o";
    两个是同一实例的引用!!!所以 a==b 返回true
      

  8.   

    就像
    Integer a = 200;
    Integer b = 200;
    System.out.println(a==b);//返回结果为false
    Integer a1 = 100;
    Integer b1 = 100;
    System.out.println(a1==b1);//返回结果为true
    这里java可能做了优化,超过128的时候,就不等了要去看java虚拟机原理吧
      

  9.   

    因为编译了,在常量池中都指向相同的地址,所以是ture,是为了少占用内存,你如果用jdk早期的版本的话,就是false。
      

  10.   

    String类里有个方法public String intern(),作用是字符串扣留:
    对于任何2个不同的String对象满足a.equals(b)为true,例如
    String a="hello";
    String b="hell"+"o";
    则对a,b其中之一调用此方法(a=a.intern()或b=b.intern())后会使得2个String变量指向同一个对象(一般是前面已存在的一个对象),另一个被舍弃。这样用==进行对象比较操作的时候会的true的结果。这个方法对于字符串常量来说是自动进行的。
    但是如果改一下String b = "hell";String c ="o";b+=c;这个时候好像要手动进行inter()操作(不知道为啥)。
      

  11.   

    道理很简单,楼主只需要明白区分编译期和运行期的概念就可以了,编译期JVM会把所有字面量的值统一保存起来,对于"hell"+"o"这样的字符串字面量计算会在编译期间就完成,所以编译期总共只生成一个"hello"对象,s1和s2都是这个常量字符串的引用,用==比较自然是true而Js没有编译的概念,Js的字符串会传值来比较,但有种情况比较特殊,就是当Js中调用new来创建字符串的时候比较的就是地址而不是值了。如果对Js感兴趣可以看看小弟写的Javascript总结
    http://topic.csdn.net/u/20080609/01/4b4266de-cfd2-4190-a3e5-0f0ec926161e.html
      

  12.   

    JavaScript 中 String 是值类型的,Java 中 String 是引用类型的。
      

  13.   

    Java字符串类(java.lang.String)是Java中使用最多的类,也是最为特殊的一个类,很多时候,我们对它既熟悉又陌生。 一、从根本上认识java.lang.String类和String池 首先,我建议先看看String类的源码实现,这是从本质上认识String类的根本出发点。从中可以看到: 
    1、String类是final的,不可被继承。public final class String。 
    2、String类是的本质是字符数组char[], 并且其值不可改变。private final char value[]; 
    然后打开String类的API文档,可以发现: 
    3、String类对象有个特殊的创建的方式,就是直接指定比如String x = "abc","abc"就表示一个字符串对象。而x是"abc"对象的地址,也叫做"abc"对象的引用。 
    4、String对象可以通过“+”串联。串联后会生成新的字符串。也可以通过concat()来串联,这个后面会讲述。 
    6、Java运行时会维护一个String Pool(String池),JavaDoc翻译很模糊“字符串缓冲区”。String池用来存放运行时中产生的各种字符串,并且池中的字符串的内容不重复。而一般对象不存在这个缓冲池,并且创建的对象仅仅存在于方法的堆栈区。下面是个系统内存示意图: 
    5、创建字符串的方式很多,归纳起来有三类: 
    其一,使用new关键字创建字符串,比如String s1 = new String("abc"); 
    其二,直接指定。比如String s2 = "abc"; 
    其三,使用串联生成新的字符串。比如String s3 = "ab" + "c"; 二、String对象的创建 String对象的创建也很讲究,关键是要明白其原理。 
    原理1:当使用任何方式来创建一个字符串对象s时,Java运行时(运行中JVM)会拿着这个X在String池中找是否存在内容相同的字符串对象,如果不存在,则在池中创建一个字符串s,否则,不在池中添加。 原理2:Java中,只要使用new关键字来创建对象,则一定会(在堆区或栈区)创建一个新的对象。 原理3:使用直接指定或者使用纯字符串串联来创建String对象,则仅仅会检查维护String池中的字符串,池中没有就在池中创建一个,有则罢了!但绝不会在堆栈区再去创建该String对象。 原理4:使用包含变量的表达式来创建String对象,则不仅会检查维护String池,而且还会在堆栈区创建一个String对象。 另外,String的intern()方法是一个本地方法,定义为public native String intern(); intern()方法的价值在于让开发者能将注意力集中到String池上。当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对象的引用。 
    3楼说的很清楚,我学过了很多。
      

  14.   

    String a="hello";
    这种形式定义的字符传放在常量池中。 只有如果值相同就只有一个副本。
      

  15.   

    String a = "hello";
    这句会在string pool 中产生一个字符串对象"hello" 将引用a指向这个对象。
    String b = "hell" + "o";
    这句会在string pool 中产生一个2个对象,"hell" 和"o"; 由于"hell" + "o" 的计算结果等于 "hello" ,这个时候java虚拟机会判断是否在string pool 中已经存在"hello" 这个对象,结果是存在, 所以直接将引用b指向string pool 中的"hello" ;这样 a和b指向同一个内存地址。而在 java语言中 "==" 比较的是两个引用的内存地址是否相同。所以返回true
      

  16.   


    你错的原因是因为,你两个字符串创建的区域是一个区域,因为在JAVA中创建字符串有两种形式,
    1
    String a=new String("abcde");
    2
    String a="abcde"
    String b="abcd"+"e"
    2所创建的是在同一区域所创建的,因为JAVA中为了方便字符串操作,但又不能采用了一个字符串重复赋值使用,所以才创建了这种形式。即a与b在同一个区域(堆栈)。
    而1则是存在于不同的堆栈。
    所以你要想把结果变为false可以用第一种方式创建两个字符串再用==比较则能成立。
      

  17.   


    var s1="hello";
    var s2="hell"+"o";
    alert(s1==s2)
    javascript没有编译,是分析字面上的字符串"hello",所以返回值为true
    public static void main(String[] args) {
            String a="hello";
            String b="hell"+"o";
            System.out.println(a==b);
        }
    java比较的是引用,应为a和b是不同的引用,所以返回值为false
      

  18.   

    因为引用相同的
    String a="abcde" 
    首先在常量池创造"abcde" 然后让a指向它(a在堆栈中),既a是他的引用String b="abcd"+"e" 
    然后是在常量池中创建"abcd" 对象和"e"对象
    因为String这个类是不能进行字符串连接的,既把"abcd"和"e"2个对象连接成一个对象
    String的”+“连接符号具体是这样实现的,先把"abcd"提出来 再把"e"提出来组合成 “abcde”,然后在常量池中创建新的对象把b指向他
    所以此时常量池中有3个对象,既"abdd" ,"e","abcde"不知道楼主明白了没
      

  19.   

    补充一下,前面说的组合成"abcde"的时候先查在常量池有没,有的直接指向存在的,没有的再创建
      

  20.   

    此回复为自动发出,仅用于显示而已,并无任何其他特殊作用
    楼主【zidasine】截止到2008-07-01 19:42:15的历史汇总数据(不包括此帖):
    发帖数:11                 发帖分:776                
    结贴数:11                 结贴分:776                
    无满意结贴数:0                  无满意结贴分:0                  
    未结数:0                  未结分:0                  
    结贴率:100.00%            结分率:100.00%            
    无满意结贴率:0.00  %            无满意结分率:0.00  %            
    敬礼!
      

  21.   

    同意,我初学,java中==比较的是字符串的引用地址;   String a="hello";
       String b="hello";
       System.out.println(a==b);
    返回是true;
       String a=new String("hello");
       String b=new String("hello");
       System.out.println(a==b);
    返回是false;
       String a=new String("hello");
       String b=new String("hello");
       System.out.println(a.eqauls(b));
    返回是true
      

  22.   

    看来,大家对String的理解还不够透彻啊。哎。……
      

  23.   

    这个回答很不错,指出了为什么a 和b会是同一个对象的引用
    3楼的回答也很好,
    21楼的回答不正确 呵呵 ,public static void main(String[] args) {
            String a="hello";
            String b="hell"+"o";
            System.out.println(a==b);
        }
    这个结果是true不是false
    结贴了
      

  24.   

    这涉及到java虚拟机对字符串常量的优化。"Hell"+"o"在虚拟机编译的时候就被视为字符串常量"Hello".所以只有一个字符串常量"Hello".没有字符串常量"Hell"和"o"还有类似的是
    final String a="Hell";String b="Hello";String c=a+"o";System.out.println(c==b);结果也是true