java高手来啊,字符串相等问题

public static final String a;
public static final String b;
public static final String c="c";
public static final String d="d";

static{
a="a";
b="b";
}

public static void main(String[] args){
String ab=a+b;
System.out.println(ab=="ab");
String cd=c+d;
System.out.println(cd=="cd");
String tmp=new String(new char[]{'c','d'});
String t=tmp.intern();
System.out.println(cd==t);
}求详细解答

这个其实很简单,但是实际中这么写代码的人会被人鄙视死的。
先说第一点
String对象是不可变的。String类中每一个看起来会修改String值的方法,实际上的都是创建了一个全

新的String对象。而用于String的+和+=是java中仅有的两个重载过的操作符。而java(1.6)编译器是

通过引入StringBuilder(你可以打开你所写的class文件看字节码,里边肯定会有invokespecial和

invokevirtual这就是初始化init方法了一个StringBuilder对象和调用其append方法,如果不想了解这

么深,括号里的内容可以忽略)来实现的+或者+=的重载,最后通过toString返回其产生的新对象(源代码里是new的)。
然而要注意一点(只针对这个题目),对于一个class来说当其成员变量是String的静态final域时,在类被编译时编译器会进行优化和改进。这里的优化就是String替换.举个例子
public static final String c="c";
public static final String d="d";
public static final String dddccc=d+d+d+c+c+c;
public static void main(String[] args){
String ccd = c+c+d;

}
会优化变成
public static final String c="c";
public static final String d="d";
public static final String dddccc="dddccc";
public static void main(String[] args){
String ccd = "ccd";
}
原因很简单编译器为了提高效率和无效代码。而如果将上述变量(a和b)的初始化话放在构造方法(虽然这里的a,b必须在static域中初始化,但非static在构造方法里)或者static域中进行的话就不能进行替换啦。static域是在类的init方法后执行(至于神马是init方法和有什么特点,你可以看看JVM相关的资料,还有至于为什么编译器可以这么优化,如果楼主对final域比较了解的话就能理解了)。

2。字符串池
这个可以把它理解成是java对字符串的一种缓存机制(虽然实际并非如此),由于字符串操作频繁,

如果没有字符串池的话,会造成大量String对象被频繁的创建和销毁。这对于java这种语言的效率来说

是不可接受的。因此java在内存中会单独开辟一块内存用来存放字符串对象(只能由String类来维护)。程序中出现的字符串常量都是在池中的。比如String a = “ab”,String c =”cd“。而new操作符产生的String对象将不会放在字符串池中。如String cd = new String("cd");是在堆中的(java中所有的对象的存放地)至于为什么,还是那句话:说来话长。
好我可以开始解释了
String ab=a+b;//通过+运算符返回新的String对象
System.out.println(ab=="ab");//"ab"是池中对象,ab没有在池中的对象不一样
结果false 不解释。
String cd=c+d;
System.out.println(cd=="cd");
编译器优化后
String cd="cd';//池中对象
System.out.println(cd=="cd");//跟自身相比肯定相等 true 不解释

String tmp=new String(new char[]{'c','d'});
这里解释一下intern的实现逻辑
如果池中已经有相同的字符串了,直接返回池中字符串,否则将tmp拷贝一份放入池中并返回池中对象
注意这里是拷贝而不是将引用指向池中对象(String是final的)
String t=tmp.intern();// 返回池中的"cd",因为已经存在了cd所以这个返回的对象跟cd没有半毛钱的关系。

System.out.println(cd==t);// 肯定是true不解释
我写了这么多,只是觉得大家对于String这个对象特别的执着,不论是面试还是考试 ,其实你只要不再循环里+或者+=字符串的话其实是没有什么问题。你平时写个 Stirng aaa = "a'+"b"的话编译器是会帮你优化的。无关痛痒。
温馨提示:答案为网友推荐,仅供参考
第1个回答  2011-03-17
的也不超过10个,而且IDE还会给你提示,比如:
String s="a string";
然后你输入s点上一个点之后IDE会出现所有可用的方法,你如果有记不住的,看一下就可以想起来了嘛,再不行还有API文档可供查阅不是吗?
张孝祥老师说:
学习程序设计,重要的是扩充知识面,你知识面广了,你就知道当遇到问题的时候去哪方面想,思路就会开阔,问题就比较容易解决。
学习完基础的Java部分,看一下《Java编程思想》这本书,它会让你提升一个档次,并且对Java语言,对编程有一个全新的理解。当然,有些概念性的抽象的东西看不懂也不要紧,那是语言发明者应该研究的问题,你只要会用就行了

还有就是多写程序,多做项目,可能你觉得自己知识掌握的还不够,但是可以边学边做嘛,做完一个比较大的项目之后,你会发现自己简直脱胎换骨了。

另外要说的是,Java与c++相比,开发同一个项目,用时是c++的一半甚至更少,就是因为它为程序员提供了快速解决问题的方案,掌握Java的纯粹的面向对象的思想,会对你有很大益处的

祝你好运
第2个回答  2011-03-16
如果是想判断字符串长度用此方法:
boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
测试两个字符串区域是否相等。
第3个回答  2011-03-16
false
true
true

"ab","cd"是字面量,存储在栈。

intern方法在jdk的解释如下:
public String intern()返回字符串对象的规范化表示形式。
一个初始为空的字符串池,它由类 String 私有地维护。
当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用。
“所有字面值字符串和字符串赋值常量表达式都使用 intern 方法进行操作。”

后面两个true都能解释,但是第一个false就不会了。
不过实际中没人会写出这样的代码,这些代码问题比较多。
相似回答