java string理解_java String 深入理解

说出下面程序的输出

classStringEqualTest {public static voidmain(String[] args) {String s1 = "Programming";

String s2 = new String("Programming");

String s3 = "Program" + "ming";

String s4=new String(s2);

String s5 = "Programming";

System.out.println(s1 == s2);//false

System.out.println(s4 == s2);//false

System.out.println(s1 == s3);//true

System.out.println(s1 == s1.intern());//true

}

}

解释:

在此引入常量池这个概念:常量池(constant

pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量

首先,我们要知道Java会确保一个字符串常量只有一个拷贝。

因为例子中的s1和s3中的”Programming”都是字符串常量,它们在编译期就被确定了,所以s1==s3为true;而”Program”和”ming”也都是字符

串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所以s3也同样在编译期就被解析为一个字符串常量,所以s3也是常量池中

”kvill”的一个引用。

所以我们得出s5==s1==s2;

用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String()

创建的字符串不放入常量池中,它们有自己的地址空间。

所以有s2!=s4

String对象的intern方法会得到字符串对象在常量池中对应的版本的引用(如果常量池中有一个字符串与String对象的equals结果是true),如果常量池中没有对应的字符串,则该字符串将被添加到常量池中,然后返回常量池中字符串的引用。

再补充介绍一点:存在于.class文件中的常量池,在运行期被JVM装载,并且可以扩充。String的intern()方法就是扩充常量池的一个 方法;当一个String实例str调用intern()方法时,Java查找常量池中是否有相同Unicode的字符串常量,如果有,则返回其的引用, 如果没有,则在常量池中增加一个Unicode等于str的字符串并返回它的引用;

案例

String s0=“kvill”;

String s1=newString(”kvill”);

String s2=newString(“kvill”);

System.out.println( s0==s1 );

System.out.println( “**********” );

s1.intern();

s2=s2.intern(); //把常量池中“kvill”的引用赋给s2

System.out.println( s0==s1);

System.out.println( s0==s1.intern() );

System.out.println( s0==s2 );

结果为:false

**********

false //虽然执行了s1.intern(),但它的返回值没有赋给s1

true //说明s1.intern()返回的是常量池中”kvill”的引用

true

关于equals()和==:

这个对于String简单来说就是比较两字符串的Unicode序列是否相当,如果相等返回true;String类已经重写过了equals方法。

而==是比较两字符串的地址是否相同,也就是是否是同一个字符串的引用。

而在符合数据类型中,则equals和==都是比较两对象的地址是否相同,除非重写equals,详见hashcode与equals的区别。

使用equals方法比较两个相同的StringBuffer对象

StringBuffer sb0=new StringBuffer("hello");

StringBuffer sb1=new StringBuffer("hello");

System.out.println(sb0==sb1);

System.out.println(sb0.equals(sb1));

System.out.println(sb0.toString().equals(sb1.toString()));false

false

true

StringBuffer 类没有重写Object类下的equals方法,所以实质还是==比较,所以如果需要比较两个StringBuffer对象是否相等则toString()方法转为String。

.关于String是不可变的

这一说又要说很多,大家只要知道String的实例一旦生成就不会再改变了,比如说:String str=”kv”+”ill”+”

“+”ans”;

就是有4个字符串常量,首先”kv”和”ill”生成了”kvill”存在内存中,然后”kvill”又和” “ 生成 ”kvill

“存在内存中,最后又和生成了”kvill

ans”;并把这个字符串的地址赋给了str,就是因为String的“不可变”产生了很多临时变量,这也就是为什么建议用StringBuffer的原

因了,因为StringBuffer是可改变的。

可不可以在分割字符串是使用多个分割符

String str="2012-05-25 13:24:16";

String[] s=str.split("-|:|\\s");for(String temp:s){

System.out.print(temp+" ");

}2012 05 25 13 24 16

关键点就是在split()方法中使用多个分割符;其实split()方法里的分割符参数是一个正则表达式,所以可以使用或操作符(|)链接多个分割符,这样在分割的时候就会按照所有的分割符对字符串进行分割了。\s表示空格,不过在字符串使用过程中还需要在\s之前添加转义字符"\",否则会出现编译错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值