使用Java语言进行编程,我们每天都要用到String类,但是以前只是拿来就用,并不知道String类的实现原理和在内存中是如何存在的,所以,是时候来仔细看看我们熟悉的String背后的故事了。
String不属于8种基本数据类型,String是一个对象。 因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。
String实际上是使用字符数组来存储的数据的。从源码可以清晰看到定义的字符数组。
String在java/lang包下面,java默认导入lang包,所以使用String类时不用导入。
String 和 CharSequence 关系
String 继承于CharSequence,也就是说String也是CharSequence类型。
CharSequence是一个接口,它只包括length(), charAt(int index), subSequence(int start, int end)这几个API接口。除了String实现了CharSequence之外,StringBuffer和StringBuilder也实现了CharSequence接口。
需要说明的是,CharSequence就是字符序列,String, StringBuilder和StringBuffer本质上都是通过字符数组实现的!
匹配相等
使用String类经常需要对两个字符串进行对比,看是否相等。这是又有==和equals两种选择,这两者方法区别很大,可能我们会弄错,下面我们对这两种方法进行详解。
首先要明白这两种方法的用途:
比较类中的数值是否相等使用equals(),比较两个包装类的引用是否指向同一个对象时用==
equals()是看数值是否相等,比较好理解。而==是看是否属于同一个对象。下面来举例说明==的使用
先明白这个概念:常量池在java用于保存在编译期已确定的,已编译的class文件中的一份数据。主要看编译 期字符串能否确定。
情况一:
String ok="ok";
String ok1=new String("ok");
System.out.println(ok==ok1);//fasle
明显不是同一个对象,一个指向字符串常量池,一个指向new出来的堆内存块,new的字符串在编译期是无法确定的。所以输出false
情况二:
String ok="apple1";
String ok1="apple"+1;
System.out.println(ok==ok1);//true
编译期ok和ok1都是确定的,字符串都为apple1,所以ok和ok1都指向字符串常量池里的字符串apple1。指向同一个对象,所以为true.
情况三:
String ok="apple1";
int temp=1;
String ok1="apple"+temp;
System.out.println(ok==ok1);//false
主要看ok和ok1能否在编译期确定,ok是确定的,放进并指向常量池,而ok1含有变量导致不确定,所以不是同一个对象.输出false
情况四:
String ok="apple1";
final int temp=1;
String ok1="apple"+temp;
System.out.println(ok==ok1);//true
ok确定,加上final后使得ok1也在编译期能确定,所以输出true
情况五:
public static void main(String[] args) {
String ok="apple1";
final int temp=getTemp();
String ok1="apple"+temp;
System.out.println(ok==ok1);//false
}
public static int getTemp()
{
return 1;
}
ok一样是确定的。而ok1不能确定,需要运行代码获得temp,所以不是同一个对象,输出false。
总结
String类具有immutable(不能改变)性质,当String变量需要经常变换时,会产生很多变量值,应考虑使用StringBuffer提高效率。在开发时,注意String的创建方法。本篇博客是本人自己学习研究的,如有错误,望修正。
评论前必须登录!
注册