Java的String类在开发时经常都会被使用到,由此可见String的重要性。经过这次认真仔细的学习了java的String类。发现了自己以前开发中对String使用的不足,特写此博客来记录自己对String的学习总结。
首先String不属于8种基本数据类型,String是一个对象。 因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。
String实际上是使用字符数组来存储的数据的。从源码可以清晰看到定义的字符数组。
String在java/lang包下面,java默认导入lang包,所以使用String类时不用导入。
1.创建方式
(1)String ok1=new String(“ok”);
(2)String ok2=“ok”;
我相信很多人都知道这两种方式定义字符串,但他们之间的差别又有多少人清楚呢。画出这两个字符串的内存示意图:
String ok1=new String(“ok”)。首先会在堆内存申请一块内存存储字符串ok,ok1指向其内存块对象。同时还会检查字符串常量池中是否含有ok字符串,若没有则添加ok到字符串常量池中。所以
new String()可能会创建两个对象.
String ok2=“ok”。 先检查字符串常量池中是否含有ok字符串,如果有则直接指向, 没有则在字符串常量池添加ok字符串并指向它.所以这种方法最多创建一个对象,有可能不创建对象
所以String ok1=new String(“ok”);//创建了两个对象
String ok2=“ok”;//没有创建对象
来两题习题看你是否真的明白了
1.下面代码创建了多少个对象?
String temp="apple";
for(int i=0;i<1000;i++)
{
temp=temp+i; <br style="word-wrap:break-word">
}
复制代码
答案:1001个
2.下面代码创建了多少个对象?
String temp=new String("apple")
for(int i=0;i<1000;i++)
{
temp=temp+i; <br style="word-wrap:break-word">
}
复制代码
答案:1002个2.匹配相等
使用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"; <br style="word-wrap:break-word">
final int temp=getTemp(); <br style="word-wrap:break-word">
String ok1="apple"+temp; <br style="word-wrap:break-word">
System.out.println(ok==ok1);//false <br style="word-wrap:break-word">
}
public static int getTemp()
{
return 1;
}
复制代码
ok一样是确定的。而ok1不能确定,需要运行代码获得temp,所以不是同一个对象,输出false。
3.Intern()方法
前面已经介绍常量池在java用于保存在编译期已确定的,已编译的class文件中的一份数据。
但我们可以通过intern()方法扩展常量池。
intern()是扩充常量池的一个方法,当一个String实例str调用intern()方法时,java会检查常量池中是否有相同的字符串,如果有则返回其引用,如果没有则在常量池中增加一个str字符串并返回它的引用。
如:
String ok="apple";
String ok1=new String("apple");
System.out.println(ok==ok1);//false
ok1=ok.intern();//获取常量池ok的引用
System.out.println(ok==ok1);//true--指向同一个对象
复制代码
4.String常用方法
(1)length() 字符串的长度
例:char chars[]={'a','b'.'c'};
String s=new String(chars);
int len=s.length();
(2)charAt() 截取一个字符
例:char ch;
ch="abc".charAt(1); 返回'b'
(3)getBytes()获取对应字节数组
例:String ok="apple";
byte[]bytes=ok.getBytes();
for(int i=0;i<bytes.length;i++)
System.out.println(bytes);//输出字节数组,范围为-128---127
(4)indexOf()和lastIndexOf()
indexOf() 查找字符或者子串第一次出现的地方。
lastIndexOf() 查找字符或者子串是后一次出现的地方。
(5)substring()
它有两种形式,第一种是:String substring(int startIndex)
第二种是:String substring(int startIndex,int endIndex)
(6)concat() 连接两个字符串
(7)replace() 替换
它有两种形式,第一种形式用一个字符在调用字符串中所有出现某个字符的地方进行替换,形式如下:
String replace(char original,char replacement)
例如:String s="Hello".replace('l','w');
第二种形式是用一个字符序列替换另一个字符序列,形式如下:
String replace(CharSequence original,CharSequence replacement)
(8)trim() 去掉起始和结尾的空格
(9)valueOf() 转换为字符串
(10)toLowerCase() 转换为小写
(11)toUpperCase() 转换为大写
(12)startsWith()和endsWith()
startsWith()方法决定是否以特定字符串开始,endWith()方法决定是否以特定字符串结束
更多方法请参考String的API
总结
String类具有immutable(不能改变)性质,当String变量需要经常变换时,会产生很多变量值,应考虑使用StringBuffer提高效率。在开发时,注意String的创建方法。本篇博客是本人自己学习研究的,如有错误,望修正。