1.String知识点及其常见的API
1.1 String是不可变对象
由于在实际开发中字符串被使用的频率非常高,当在频繁的使用某个字符串时,会频繁的创建对象,java为此采用了优化的措施,使得String对象不可变,一旦在内存中创建,内容不能发生变化,一旦对字符串内容的改变就会重新创建对象,这样就会最大程度的重用相同的内容,从而减少对系统资源的开销,字符串是如何的重用的?这就要从JVM中找答案。
1.2 String常量池
当我们通过字面量,常量来初始化一个字符串时,JVM首先会从字符串的常量池(一个JVM内部维护的内存区域《方法区中》,用来保存已经创建过的字符串对象)中查询用来保存该字符串的对象是否存在,若存在则直接引用,若不存在则创建该字符串对象并存入常量池,然后引用它。因为字符串内容不能改变,所以我们可以放心的重用他们。
代码体现:
public class StringDemo
{
public static void main(String[] args)
{
//java使用字面量创建对象
String s1 = "java123";
//字面量对象一旦发现曾经创建过的对象就会重用
//这里就使用到了常量池
String s2 = "java123";
System.out.println(s1 == s2);// true == 比较的是对象的地址值
System.out.println(s1.equals(s2));// true equals 比较的是对象的是否相等
String s3 = new String("java123");//这里创建了两个对象
System.out.println(s1 == s3);//false
System.out.println(s1.equals(s3));//ture
//有关java编译的原理问题
/*
* java编译器的优化措施
* 单有一个计算表达式参与运算的值都是字面量
* 那么就直接在编译的时候,进行计算,编译到class文件
*
*/
String s4 = "java"+"123";//java在编译时就进行计算
System.out.println(s1 == s4);//true
String s5 = "java";
String s6 = s5 + "123";//有变量时,编译时不计算,运行时计算
System.out.println(s1 == s6);//false
}
}
1.3 String的常用API
1.3.1 内存编码及长度(length)
java存储每一个字符均使用2个字节保存,使用的是Unicode编码。并且任何一个字符(无论是英文还是汉字)每个字符的长度都是1。所以字符串的长度就是该字符串所有的字符个数。
获取字符串长度:int length();
String str = "java";
System.out.println(str.length());//结果:4
1.3.2 使用indexOf()方法获取下标位置
int indexOf(int ch):检查给定的字符在当前字符串中第一次出现的下标位置,当不包含改字符时,返回-1
代码演示:
String str = "thinking in java";
//第一次出现的位置
int index = str.indexOf("in");
System.out.println(index);// 2
//从某个位置开始查询
index = str.indexOf("in", 3);//从下标为3开始查找
System.out.println(index);// 5
//最后一次出现位置
index = str.lastIndexOf("in");
System.out.println(index);// 9
1.3.3 char charAt(int index)方法的使用
给定一个下标位置,从而获取该字符串中这个位置的字符。
代码演示:
String str = "thinking in java";
//获取下标为3的字符
char ch = str.charAt(3);
System.out.println(ch); // n
1.3.4 substring获取子串
String substring(int begin, int end):截取字符串中的部分内容以获取子字符串,该注意的是传入的两个数字的范围是“含头不含尾”。
代码演示:
String str = "thinking in java";
String sub = str.substring(12, 16);
System.out.println(sub); // java
1.3.5 trim方法的使用
String trim():将字符串两边的空白(如 空格)去掉。
代码演示:
String str = " hello world ";
String t = str.trim();
System.out.println(t); //hello world
1.3.6 startsWith和endsWith的使用
boolean startsWith(String suffix):判断当前的字符串是否与给定的字符串开头(必须是一模一样)。
boolean endsWith(String suffix):判断当前字符串是否与给定的字符串结尾。
代码演示:
String str = "thinking in java";
boolean starts = str.startsWith("thin");
System.out.println("starts:"+starts);// true
boolean ends = str.endsWith("java");
System.out.println("ends:"+ends); //true
1.3.7 字符串大小写的转换
String toUpperCase():将字符串转换为大写。
String toLowerCase():将字符串转换为小写。
代码演示:
String str = "HelloWorld";
String lower = str.toLowerCase();//转换为小写
String upper = str.toUpperCase();//转换为大写
System.out.println("lower:"+lower);//helloworld
System.out.println("upper:"+upper);//HELLOWORLD
1.3.8 静态方法 valueOf 的使用
valueOf()方法有许多重载的方法,可以将其他的基本类型的值以字符串的形式表示
代码演示:
double pi = 3.1415926;
int value = 123;
boolean flag = true;
char[] charArr = { 'a', 'b', 'c', 'd', 'e', 'f', 'g' };
/**
输出的结果都是字符串的形式
*/
String str = String.valueOf(pi);
System.out.println(str); // 3.1415926
str = String.valueOf(value);
System.out.println(str); //123
str = String.valueOf(flag);
System.out.println(str);// true
str = String.valueOf(charArr);
System.out.println(str);// abcdef
1.4 StringBuilder和StringBuffer的区别
1.4.1 StringBuilder简介及常用API
封装的是可变的字符串,当改变字符串的内容时不会重新的创建对象,是在原对象的基础上进行修改。
注意:它是是非线程安全的,并发处理的,性能稍快;
常用API
append(String str):追加字符串;
insert (int dstOffset,String s):插入字符串;
delete(int start,int end):删除字符串;
replace(int start,int end,String str): 替换字符串;
reverse():字符串反转。
代码演示:
String str = "努力学习java";
StringBuilder sb = new StringBuilder(str);
//追加字符串
sb.append("改变世界!");
//插入字符串
sb.insert(8, ",");
//替换字符串
sb.replace(4, 8, "");
System.out.println(sb.toString());// 努力学习,改变世界!
//反转字符串
sb.reverse();
System.out.println(sb.toString()); //!界世变改,习学力努
1.4.2 StringBuffer简介及常用API
基本上和StringBuilder一样
注意:它是线程安全的,同步处理,性能稍慢;