----------- Android培训、Java培训、Java学习型技术博客、期待与您交流! ------------
Java的字符串类(java.lang.String)是Java中使用最多的类,也是最为特殊的一个类
1.String不属于8种基本数据类型,String是一个对象,因为对象的默认值是null,所以String的默认值也是null;但它又是一种特殊的对象,有其它对象没有的一些特性。
2. new String()和new String(“”)都是申明一个新的空字符串,是空串不是null;
3.创建字符串的方式很多,归纳起来有三类:
(1)使用new关键字创建字符串,比如String s1 = new String("jeek");
(2)直接指定。比如String s2 = "jeek";
(3)使用串联生成新的字符串。比如String s3 = "je" + "ek";
4.String str="jeek";和String str=new String ("jeek");的区别:这就涉及到了常量池这个概念.
常量池(constant pool)指的是在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于 类、方法、接口等中的常量,也包括字符串常量。
例:
String s0=”jeek”;
String s1=”jeek”;
String s2=”je” + “ek”;
System.out.println( s0==s1 );
System.out.println( s0==s2 );
结果都为true.
首先,我们要知结果为道Java会确保一个字符串常量只有一个拷贝。
因为例子中的s0和s1中的”jeek”都是字符串常量,它们在编译期就被确定了,所以s0==s1为true; 而”je”和”ek”也都 是字符串常量,当一个字符串由多个字符串常量连接而成时,它自己肯定也是字符串常量,所 以s2也同样在编译 期就被解 析为一个字符串常量,所以s2也是常量池中”jeek”的一个引用。 所以我们得出 s0==s1==s2;
用new String() 创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池 中,它们 有自己的地址空间。
例:
String s0=”jeek”;
String s1=new String(”jeek”);
String s2=”je” + new String(“ek”);
System.out.println( s0==s1 );
System.out.println( s0==s2 );
System.out.println( s1==s2 );
上述打印结果都为false.
例中s0还是常量池中”jeek”的应用,s1因为无法在编译期确定,所以是运行时创建的新对象”jeek”的引用,s2因 为有后 半部分new String(“ek”)所以也无法在编译期确定,所以也是一个新创建对象”jeek”的应用;明白了这些 也就知 道为何得 出此结果了。
String对象的创建原理
原理1:当使用任何方式来创建一个字符串对象s时,Java运行时(运行中JVM)会拿着这个X在String池中找是否 存在内容相同的字符串对象,如果不存在,则在池中创建一个字符串s,否则,不在池中添加。
原理2:Java中,只要使用new关键字来创建对象,则一定会(在堆区或栈区)创建一个新的对象。
原理3:使用直接指定或者使用纯字符串串联来创建String对象,则仅仅会检查维护String池中的字符串,池中没有 就在池中创建一个,有则罢了!但绝不会在堆栈区再去创建该String对象。
原理4:使用包含变量的表达式来创建String对象,则不仅会检查维护String池,而且还会在堆栈区创建一个String 对象。
另外,String的intern()方法是一个本地方法,定义为public native String intern(); intern()方法的价值在于让开发者 能将注意力集中到String池上。当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象 由 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并且返回此 String 对 象的引用。
String类的不可变
string类型是不可改变的,也就是说,当你想改变一个string对象的时候,比如String name= "jeek " ;现在修改为name="wong";
那么虚拟机不会改变原来的对象,而是生成一个新的string对象,然后让name去指向它,如果原来的那个 "jeek "没有任何对象去引用它,虚拟机的垃圾回收机制将接收它。
String类中常用方法
1.charAt方法:该方法的作用是按照索引值(规定字符串中第一个字符的索引值是0,第二个字符的索引值是1,依次类推),获得字符串中的指定字符.
eg: String s = "jeek";
char c = s.chatAt(1);则变量c的值是'e'.
2.compareTo方法:该方法的作用是比较两个字符串的大小,比较的原理是依次比较每个字符的字符编码。首先比较两个字符串的第一个字符,如果第一个字符串的字符编码大于第二个的字符串的字符编码,则返回大于0的值,如果小于则返回小于0的值,如果相等则比较后续的字符,如果两个字符串中的字符编码完全相同则返回0。还存在一个类似的方法compareToIgnoreCase,这个方法是忽略字符的大小写进行比较,比较的规则和compareTo一样.
3.concat方法:该方法的作用是进行字符串的连接,将两个字符串连接以后形成一个新的字符串.
eg:
String s = "jeek";
String s1 = "wong";
String s2 = s.concat(s1);
则连接以后生成的新字符串s2的值是"jeekwong",而字符串s和s1的值不发生改变。
如果需要连接多个字符串,可以使用如下方法:
String s = "jeek";
String s1 = "wong";
String s2 = "iteye;
String s3 = s.concat(s1).concat(s2);
则生成的新字符串s3的值为"jeekwongiteye".
其实在实际使用时,语法上提供了一种更简单的形式,就是使用"+"进行字符串的连接。例如:String s = "jeek" + "wong";则字符串s的值是"jeekwong",这样书写更加简单直观。而且使用"+"进行连接,不仅可以 连 接字符串,也可以连接其他类型。但是要求进行连接时至少有一个参与连接的内容是字符串类型。而 且"+"匹配的顺序是从左向右,如果两边连接的内容都是基本数字类型则按照加法运算,如果参与连接的内容有 一个是字符串才按照字符 串进行连接。
int a = 123;
String s = "jeek" + a + 1;
则连接以后字符串s的值是"jeek1231",计算的过程为首先连接字符串"jeek"和变量a的值,生成字符 串"jeek123",然后使用该字符串再和数字1进行连接生成最终的结果。
而如下代码:
int a = 10;
String s = a + 5 + "123";
则连接以后字符串s的值是"15123",计算的过程为首先计算a和数字5,由于都是数字型则进行加法运算或者数 字值15,然后再使用数字值15和字符串"123"进行连接获得最终的结果。
而下面的连接代码是错误的:
int a = 12;
String s = a + 5 + 's';
因为参与连接的没有一个字符串,则计算出来的结果是数字值,在赋值时无法将一个数字值赋值给字符串
4.endsWith方法:该方法的作用是判断字符串是否以某个字符串结尾,如果以对应的字符串结尾,则返回true
5.equals方法:该方法的作用是判断两个字符串对象的内容是否相同。如果相同则返回true,否则返回false
6.getBytes方法:该方法的作用是将字符串转换为对应的byte数组,从而便于数据的存储和传输.
public class StringDemo
{
public static void main(String[] args)
{
//练习模拟trim方法,去除空格
trim();
//将字符串反转
reverseString();
//将字符串局部反转
reverseSubString();
}
public static void reverseSubString()
{
String str = "jeek wong";
//012345678
//char[] chs = str.toCharArray();
reverseSub(str, 5, 8);
System.out.println(str);
}
public static void reverseSub(String str, int start, int end)
{
String subString = str.substring(start, end);//5.7 won
String subStringReverse = reverse(subString.toCharArray());
str.replace(subString, subStringReverse);
}
public static void trim()
{
String str = " jeek wong ";
System.out.println(str);
System.out.println("-----------------");
int start = 0;
int end = str.length() - 1;
while(start <= end && str.charAt(start) == ' ')
start++;
while(start <=end && str.charAt(end) == ' ')
end--;
str = str.substring(start, end + 1);
System.out.println(str);
}
public static void reverseString()
{
//将字符串变为数组,将数组反转,将数组变为字符串
String str = "jeek wong";
char[] chs = str.toCharArray();
reverse(chs);
System.out.println(new String(chs));
}
private static String reverse(char[] arr)//won
{
for(int start = 0, end = arr.length - 1; start < end; start++, end--)
{
swap(arr, start, end);
}
return new String(arr);//now
}
private static void swap(char[] arr, int x, int y)
{
char temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
}
7.indexOf方法:该方法的作用是查找特定字符或字符串在当前字符串中的起始位置,如果不存在则返回-1
8.length方法:该方法的作用是返回字符串的长度,也就是返回字符串中字符的个数。中文字符也是一个字符
9.replace方法:该方法的作用是替换字符串中所有指定的字符,然后生成一个新的字符串。经过该方法调用以后,原来的字符串不发生改变.
10.split方法:该方法的作用是以特定的字符串作为间隔,拆分当前字符串的内容,一般拆分以后会获得一个字符串数组.
public class StringTest2
{
public static void main(String[] args)
{
//String str = "huangjing";
//System.out.println(getSubCount(str, 'p'));
// String str1 = "hhuuaannhhggjjiinngghhkkoonn";
// System.out.println(getSubStringCount_1(str1, "hh"));
split();
}
//获取字符串中某个字符的个数
public static int getSubCount(String str, char key)
{
int num = 0;
char[] chs = str.toCharArray();
if(!(str.indexOf(key) == -1))
{
for(int i = 0; i < chs.length; i++)
{
if(chs[i] == key)
num++;
}
}
return num;
}
//获取某个字符串中子串的个数方式一
public static int getSubStringCount(String str, String key)
{
int count = 0;
int index = 0;
while((index = str.indexOf(key)) != -1)
{
str = str.substring(index + key.length());
System.out.println("str=" + str);
count++;
}
return count;
}
//获取某个字符串中子串的个数方式二
public static int getSubStringCount_1(String str, String key)
{
int count = 0;
int index = 0;
while((index = str.indexOf(key, index)) != -1)
{
index = index + key.length();
//System.out.println("str=" + str);
count++;
}
return count;
}
public static void split()
{
String str1 = "aabbcc";
System.out.println(str1.split("aa").length);//2
String str2 = "bbccaa";
System.out.println(str2.split("aa").length);//1
//注意两者切割的不同
}
11.startsWith方法:该方法的作用和endsWith方法类似,只是该方法是判断字符串是否以某个字符串作为开 始.
12.substring方法:该方法的作用是取字符串中的“子串”,所谓“子串”即字符串中的一部分.
/*
* 求两个字符串中最长的相同字串//
*/
public class StringTest3
{
public static void main(String[] args)
{
String str1 = "abcdefg";
String str2 = "abdcef";
System.out.println(maxLength(str1, str2));
}
public static String maxLength(String str1, String str2)
{
for(int x = 0; x < str2.length(); x++)
{
for(int y = 0, z = str2.length() - x; z <= str2.length(); y++, z++)
{
String temp = str2.substring(y, z);
System.out.println(temp);
//
// if(str1.contains(temp))
// return temp;
}
}
return "";
}
}
13.toCharArray方法:该方法的作用和getBytes方法类似,即将字符串转换为对应的char数组
StringBuffer和StringBuilder
package cn.itcast.day;
/*
* StringBuffer是字符串缓冲区,是一个容器,
* 1.长度是可以变化的,
* 2.可以添加任意类型的数据
* 3.最后全部由toString()变为字符串
* CURD create update read delete
*
* 增加append()方法没有byte和short参数 方法调用链
*
* 插入insert() 存在index才可以插入
*
* 删除delete(start, end)删除缓冲区中指定数据
* deleteCharAt(index)
* 清空缓冲区 sb = new StringBuffer();
* 全部清空sb.delete(0, sb.length)
*
* 获取
* charAt(index)
* indexOf(String)
* length
* String subString(start, end)
*/
public class StringBufferDemo
{
public static void main(String[] args)
{
StringBuffer sb = new StringBuffer();
sb.append(32).append("aca");
sb.insert(1, "qq");
sb.delete(1, 3);
sb.deleteCharAt(2);
// StringBuffer sb1 = sb.append(32);
//
System.out.println(sb);
// System.out.println(sb1);
}
}
/*
* StringBuilder JDK1.5
* StringBuffered线程同步
* StringBuilder线程不同步.
*
* 升级:
* 1.提高效率
* 2.简化书写
* 3.提高安全性
*
*/
Done...