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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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"的话编译器是会帮你优化的。无关痛痒。
参考技术A 的也不超过10个,而且IDE还会给你提示,比如:
String s="a string";
然后你输入s点上一个点之后IDE会出现所有可用的方法,你如果有记不住的,看一下就可以想起来了嘛,再不行还有API文档可供查阅不是吗?
张孝祥老师说:
学习程序设计,重要的是扩充知识面,你知识面广了,你就知道当遇到问题的时候去哪方面想,思路就会开阔,问题就比较容易解决。
学习完基础的Java部分,看一下《Java编程思想》这本书,它会让你提升一个档次,并且对Java语言,对编程有一个全新的理解。当然,有些概念性的抽象的东西看不懂也不要紧,那是语言发明者应该研究的问题,你只要会用就行了

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

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

祝你好运
参考技术B 如果是想判断字符串长度用此方法:
boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
测试两个字符串区域是否相等。
参考技术C false
true
true

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

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

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

jvm高手来啊,xms和xmx一样出现问题.

我看到这样的一段话:
我把-Xms和-Xmx设置成一样时,那就意味着,只有当java使用完所有内存时才会回收垃圾,这样一来内存当然不停的涨。
我就不理解内存不停的涨,我是这样想的,-Xms和-Xmx设置成一样时,xmx已有最大值啊,为什么还说不停的涨啊。

这句话里“内存不停的涨”的意思是在Xmx的范围内内存的占用会不停的涨,但是一旦涨到达到Xmx值的时候就会进行垃圾回收了,内存分配不会超过这个值的,如果进行垃圾回收后仍然不够用,就会报内存溢出的错误。

附:
JVM申请一块内存的过程:
A. JVM会试图为相关Java对象在Eden中初始化一块内存区域
B. 当Eden空间足够时,内存申请结束。否则到下一步
C. JVM试图释放在Eden中所有不活跃的对象(这属于1或更高级的垃圾回收);释放后若Eden空间仍然不足以放入新对象,则试图将部分Eden中活跃对象放入Survivor区/OLD区
D. Survivor区被用来作为Eden及OLD的中间交换区域,当OLD区空间足够时,Survivor区的对象会被移到Old区,否则会被保留在Survivor区
E. 当OLD区空间不够时,JVM会在OLD区进行完全的垃圾收集(0级)
F. 完全垃圾收集后,若Survivor及OLD区仍然无法存放从Eden复制过来的部分对象,导致JVM无法在Eden区为新对象创建内存区域,则出现”out of memory错误”

另:
xms/xmx:定义YOUNG+OLD段的总尺寸,ms为JVM启动时YOUNG+OLD的内存大小;mx为最大可占用的YOUNG+OLD内存大小。在用户生产环境上一般将这两个值设为相同,以减少运行期间系统在内存申请上所花的开销。追问

我的意思是ms和mx设置一样时,把ms看成mx,那么启动后,内存的大小是最大的,但是这个最大是规定了,为什么规定了还不停的涨。

追答

YOUNG+OLD段的总尺寸不会超过你设置的mx值的,如果超过的话会报“out of memory错误”;那个所谓的”不停的涨“的意思是在mx的范围内不停的涨,直到达到这个值。

参考技术A 只有当java使用完所有内存时才会回收垃圾,这样一来内存当然不停的涨。这说的不对!
jvm gc是分代进行的,大致分为年轻代、老年代和持久代,-Xms和-Xmx是针对heep设置的,也就是年轻代和老年代,一定次数的年轻代gc还存活的对象或年轻代大小不够放的对象才会进老年代,而老年代的空间不够用时才会进行一次full gc。
所以说如果不存在内存泄漏的情况下内存应该不会不停的涨,当然超过了就内存溢出了
可以了解下jvm gc
参考技术B 只有当java使用完所有内存时才会回收垃圾,这样一来内存当然不停的涨。这说的不对

以上是关于java高手来啊,字符串相等问题的主要内容,如果未能解决你的问题,请参考以下文章

PHP正则表达式高手来啊

java异常求助~高手来啊

Delphi 图像比例缩放问题 高手来啊

Delphi 图像比例缩放问题 高手来啊

关于ubuntu 10.10中的initramfs问题,高手来啊--

Java给字符串替换几个词文本...急,高手来吧...