今天看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改怎么解释呢
在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改怎么解释呢
楼主【zidasine】截止到2008-07-01 15:08:01的历史汇总数据(不包括此帖):
发帖数:11 发帖分:776
结贴数:11 结贴分:776
未结数:0 未结分:0
结贴率:100.00% 结分率:100.00%
敬礼!
public static void main(String[] args) {
String a="hello";
String b=new String("hello");
System.out.println(a==b);
}
这样的结果就是false
一、从根本上认识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 对象的引用。 引自他处!
java是编译型语言,在编译器进行了优化
其实这个就等于String b = "hello";
你试一试
String c = "o";
String b = "hell" + c;
结果就为False
对象判断相等是用基类Object中equals方法。
所以地址相同,当然就是true
String b = "Hell"+"o";
两个是同一实例的引用!!!所以 a==b 返回true
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虚拟机原理吧
对于任何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()操作(不知道为啥)。
http://topic.csdn.net/u/20080609/01/4b4266de-cfd2-4190-a3e5-0f0ec926161e.html
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楼说的很清楚,我学过了很多。
这种形式定义的字符传放在常量池中。 只有如果值相同就只有一个副本。
这句会在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
你错的原因是因为,你两个字符串创建的区域是一个区域,因为在JAVA中创建字符串有两种形式,
1
String a=new String("abcde");
2
String a="abcde"
String b="abcd"+"e"
2所创建的是在同一区域所创建的,因为JAVA中为了方便字符串操作,但又不能采用了一个字符串重复赋值使用,所以才创建了这种形式。即a与b在同一个区域(堆栈)。
而1则是存在于不同的堆栈。
所以你要想把结果变为false可以用第一种方式创建两个字符串再用==比较则能成立。
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
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"不知道楼主明白了没
楼主【zidasine】截止到2008-07-01 19:42:15的历史汇总数据(不包括此帖):
发帖数:11 发帖分:776
结贴数:11 结贴分:776
无满意结贴数:0 无满意结贴分:0
未结数:0 未结分:0
结贴率:100.00% 结分率:100.00%
无满意结贴率:0.00 % 无满意结分率:0.00 %
敬礼!
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
3楼的回答也很好,
21楼的回答不正确 呵呵 ,public static void main(String[] args) {
String a="hello";
String b="hell"+"o";
System.out.println(a==b);
}
这个结果是true不是false
结贴了
final String a="Hell";String b="Hello";String c=a+"o";System.out.println(c==b);结果也是true