一、字符串
String 是一个final类 不能复写 不能有子类
1. 用双引号引起的都是字符串对象 , 该对象位于常量池中
2. 字符串中==与equals的区别
1--> String s1= new String("abc");
String s2= new String("abc");
2--> String t1 = "abc";
String t2 = "abc";
s2 = s2 + " java";
t2 = t2 + " java";
`① s1 == s2 结果是false 因为创建了两个字符串对象,s1 s2分别指向堆中的两个对象
② s1.equals(s2)结果为true 因为String已经对Object类的equals方法进行了复写,
Object 的equals相当于==
③ s1 == t1 结果为false 因为堆中的字符串对象的地址跟常量池地址不一样
④ s1.equals(t1) 结果为true 内容相等
⑤ t1 == t2 结果为true 因为t1 t2指向了常量池中同一个字符串常量
⑥ t1.equals(t2) 结果为true 内容相等
⑦ s2 跟 " java"连接后指向常量池中新建的 "abc java"的字符串常量,s2原来指向的堆内存中的 abc"对象随垃圾回收器回收
⑧ t2 跟" java"连接后也指向常量池中的"abc java",t2原来指向的常量池中的"abc"还存在于常量 池中
上面用new String()创建的字符串不是常量,不能在编译期就确定,所以new String()
创建的字符串不放入常量池中,他们有自己的地址空间,String 对象(内存)的不变性机制会
使修改String字符串时,产生大量的对象,因为每次改变字符串,都会生成一个新的String。
java 为了更有效的使用内存,常量池在编译期遇见String 字符串时,它会检查该池内是否已
经存在相同的String 字符串,如果找到,就把新变量的引用指向现有的字符串对象,不创建
任何新的String 常量对象,没找到再创建新的。所以对一个字符串对象的任何修改,都会产生
一个新的字符串对象,原来的依然存在,等待垃圾回收。
一个字符串的例子
class StringDemo
{
public static void main(String[] args)
{
/*字符串是常量;它们的值在创建之后不能更改。字符串缓冲区支持可变的字符串。
因为 String 对象是不可变的,所以可以共享。例如: */
String str = "abc";
// 等效于:
char data[] = {'a', 'b', 'c'};
String str = new String(data);
//空字符串的定义
//String str1 = "";等同于
String str1 = new String();
//字符串一旦被初始化就不可以被改变
String s = "abc";
s = "cde";//abc仍然在内存中 s由指向"abc"改为指向"cde"字符串
//"=="与equals()的区别
String s1 = "abc";//s1代表一个对象,
String s2 = new String("abc");//s2在内存中有两个对象 ,
String s3 = "abc";
System.out.println(s1==s2); //返回fault ,s1与s2分别指向两不同对象,两对象在内存中不同位置
System.out.println(s1.equals(s2));//,返回true,String复写了Object类的equals方法,该方法比较的是字符串是否相同
System.out.println(s1==s3); //返回true,s1与s3指向的是同一个对象
}
}
3. 常量池
3.1. 什么是常量池?
常量池在java用于保存在编译期已确定的,已编译的class文件中的一份数据。它包括了关于 类,方法,接口 , 字段等中的常量,也包括java中用得很多的字符串常量,如String s = "java"
故认为常量池是JVM在方法区中为它们开辟一块特殊的内存空间.常量池中除了包含代码中所定
义的各种基本类型(如int、long等等)和对象型(如String及数组)的常量值外,还包 含一些 以 文本形式出现的符号引用,比如:
①类或接口的全限定名,
②超类的全限定名,
③父接口的全限定名,
④类字段名和所属类型名,
⑤类方法名和返回类型名、以及参数名和所属类型名,
⑥字符串字面值。
常量池技术是为了方便快捷地创建某些对象而出现的,当需要一个对象时,就可以从池中取一个
出来(如果池中没有则创建一个)则在需要重复创建相等变量时节省了很多时间和空间。常量池其实也就是一个内存空间,不同于使用new关键字创建的对象内存空间
3.2. 八种基本类型的包装类和对象池
java中基本类型的包装类的大部分都实现了常量池技术,这些类是
Byte,Short,Integer,Long,Character,Boolean,
另外两种浮点数类型的包装类则没有实现 , 另外 Byte,Short,Integer,Long,Character这5种前四种整型的包装类也只是在-128~127范围内,Character在0~127范围内时才可使用对象 池,也即对象不负责创建和管理大于127或小于-128的这些类的对象。
注意: 基本数据类型使用常量池技术的前提是用自动装箱装将基本类型数据到包装类的对象,通 过new方法包装的不会放常量池中,能使用常量池的是通过自动装箱包装的Boolean,或通 过自动装箱包装的Byte,Short,Integer,Long,Character且范围在小于等于127 的包装类数 据
3.2.1. 基本数据类型对象的包装类
boolean Boolean
byte Byte
char Character
short Short
int Integer
long Long
float Float
double Double例子:
① //在值小于127时可以使用常量池
Integer i1=127;
Integer i2=127;
System.out.println(i1==i2); //输出true② //值大于127时,不会从常量池中取对象
Integer i3=128;
Integer i4=128;
System.out.println(i3==i4); //输出false③ //Boolean类也实现了常量池技术
Boolean bool1=true;
Boolean bool2=true;
System.out.println(bool1==bool2); //输出true④ //浮点类型的包装类没有实现常量池技术
Double d1 = 2.3;
Double d2 = 2.3;
System.out.println(d1==d2);//输出false
3.2.2. 基本数据类型对象包装类的最常见作用:
1)用于基本数据类型与字符串类型之间的转换
a基本数据类型转成字符串:
基本数据类型+""
基本数据类型.toString(基本数据类型的值)
如:Integer.toString(33); 将33整数转换成"33"
b字符串转成基本数据类型
xxx a = Xxx.parseXxx(String s);
如: int a = Integer.parseInt("123");
double d = Double.parseDouble("123.12");
2)进制转换
a 十进制转换成其他进制
Integer.toBinaryString();
Integer.toHexString();
Integer.toOctalString();b 其他进制转换成十进制
static int parseInt(String s) 将字符串参数作为有符号的十进制整数进行解析。
static int parseInt(String s, int radix) 使用第二个参数指定的基数,将字符串参 数解析为有符号的整数
3.2.3. 基本数据类型与包装类的区别
1). 基本数据类型声明的是变量,int a
包装类声明是对象,Integer i;
2). 基本数据类型的变量没有方法,不是对象,不能作为对象调用toString()、hashCode()、getClass()、equals()等等方法。
3)基本类型变量存放的是基本类型数据的内容
包装类声明的引用变量存放的是包装着基本类型数据内容的对象的地址值
3.2.4. 装箱和拆箱
装箱:将基本数据类型包装成对应的包装类,使它们可以具有对象的特质,从而使用 该包装类的方法对包装进来的数进行操作
拆箱:将包装类转换对应的基本数据类型,跟装箱的方向相反,将引用类型的对象重 新简化为值类型的数据。
JDK1.5版本之后出现的新特性:8种基本类型都实现了自动装箱拆箱功能
自动装箱拆箱时
自动对 Byte,Short,Integer,Long,Character 装箱时,对于前四种从-128到127之间的值对于Character的0到127之间的值被装箱为对象后,存放在对象池中, 会
在内存中被重用
JDK1.5版本之前
int i = 2 ;
Integer j = new Integer(i); //手动装箱操作
int k = j.intValue();//手动拆箱操作
JDK1.5版本之后
int i = 2 ;
Integer j=i; //自动装箱操作
int k=j; //自动拆箱操作
4. Java 语言提供对字符串串联符号("+")以及将其他对象转换为字符串的特殊支持。
字符串串联是通过 StringBuilder(或 StringBuffer)类及其 append 方法实现的。
5. 字符串常见操作:
5.1. 获取
5.1.1. 获取字符串长度
int length() 方法获取字符串的长度,即字符串中的字符(Unicode)个数;
5.1.2. 根据位置获取某字符
char charAt(int index)
5.1.3. 获取某字符位置
int indexOf(int ch) 根据字符获取其在字符串中第一次出现的位置
int indexOf(int ch,int fromIndex) 获取某字符在字符串中指定位置开始第一次出现的 位置
int lastIndexOf(int ch) 根据字符获取其在字符串中最后一次出现处的索引
int lastIndexOf(int ch,int fromIndex) 根据字符获取其在字符串中某位置开始反向最 后一次出现处的索引。
5.1.4. 获取子串
String substring(int beginIndex) 返回一个新的字符串,它是此字符串指定位置到结尾 的一个子字符串。
String substring(int beginIndex, int endIndex) 返回一个新字符串,它是此字符串指 定位置到另一位置的一个子字符串。
5.2. 判断
5.2.1. 判断字符串是否包含指定字符串 boolean contains(String str)
也可以用 indexof(String str) 来判断,若返回-1 表示该字符串不包含指定字符串,返回非-1值表示包含5.2.2. 判断字符串是否有内容 boolean isEmpty()
5.2.3. 判断字符串是否以指定内容开头 boolean startsWith(String str)
5.2.4. 判断字符串是否以指定后缀结尾 boolean endsWith(String str)
5.2.5. 判断字符串内容是否相同 boolean equals(String str) 复写Object类中的equals方法
5.2.6. 判断字符串内容是否相同 并忽略大小写 boolean equalsIgnoreCase(String str)
5.2.7. 判断字符串是否匹配给定的正则表达式。 boolean matches(String regex)
5.3. 转换
5.3.1. 可以将字节数组,字符数组转换成字符串
可以将StringBuffer或StringBuilder转换成String
通过String构造方法直接得到一个String的副本
5.3.1.1. 通过String构造方法,可以将字节数组转成字符串
String(byte[] b)通过平台默认的字符集解码指定字节数组构造String对象
String(byte[] bytes,Charset charset)根据指定的字符集解码指定字节数组构造
String(byte[] bytes,String charsetName)同上,只是同字符集的字符串形式指定
String(byte[] b,int offset,int ength)使用平台默认字符集解码指定字节数组的某 范围内的子数组构造String
String(byte[] bytes,int offset,int ength ,Charset charset)根据指定字符集解码指 定字节数组的指定范围内的子数组构造新的String
String(byte[] bytes,int offset,int ength ,String charset)同上,只是以字符串形式 指定字符集
5.3.1.2. 通过String构造方法, 可以将字符数组转成字符串,
通过静态方法valueOf(char[] ch) 也可以将字符数组转换成字符串
String(char[] ch) 创建字符串,字符串的值就是字符数组的元素序列
String(char[] ch, int offset, int count) 将字符数组指定子数组转换成字符串
5.3.1.3. 通过String构造方法, 将StringBuffer转换为字符串
String(Stringbuffer buffer)
5.3.1.4. 通过String构造方法, 将StringBuilder转换为字符串
String(StringBuilder builder)
5.3.1.5. 通过String的构造方法得到一个String的副本
String(String org)
5.3.2. 可以将字符串转换成数组
5.3.2.1. 将字符串转成字符数组
char[] toCharArray()
5.3.2.2. 将字符串转换成字节数组
byte[] getBytes() 按平台默认字符集转换byte[] getBytes(String c) 按指定字符集转换
5.3.2.3. 将基本数据类型(不包括short和byte)或char[]或Object转换成字符串
static String valueOf(boolean/char/char[]/int/double/float/long/Object)
static String valueOf(char [] ch)
static String copyValueOf(char [] ch)
static String copyValueOf(char[] ch,int offset, int count)
5.3.3. 字符串中字符大小写转换
String toLowerCase() 使用默认语言环境的规则将字符串中所有字符转换成小写
String toUpperCase() 使用默认语言环境的规则将字符串中所有字符转换成大写String toUpperCase(Locale locale) 使用给定 Locale 的规则将String 中的所有字符都 转换为大写
String toLowerCase(Locale locale) 使用给定 Locale 的规则将此String中的所有字符都 转换为小写。
5.4. 替换
5.4.1. String replace(char oldchar,char newchar);
在替换的时候创建一个新的字符串对象,而不是替换换字符串对象中的字符,如果要替` 换的字符不存在返回的还是原字符串
5.4.2. String replaceAll(String regex, String replacement)
使用给定的 字符串替换此字符串所有匹配给定的正则表达式的子串
5.4.3. String replaceFirst(String regex, String replacement)
使用给定的 字符串替换此字符串匹配给定的正则表达式的第一个子字符串。
5.5. 切割
5.5.1. String[] split(String regex) 根据给定正则表达式的匹配拆分此字符串。
5.5.2. String[] split(String regex, int limit) 根据匹配给定的正则表达式来拆分此字符串。
此方法等效于Pattern.compile(regex).split(str, n)5.6. 连接
5.6.1. String concat(String str) 将指定字符串连接到此字符串的结尾。
5.7. 去空格
将字符串两端多个空格去除
String trim() 返回字符串的副本,忽略前导空白和尾部空白。
5.8. 比较
对两个字符串进行自然顺序的比较 , 若相等返回0,大于返回一个正数,小于返回负数
int compareTo(String anotherString) 按字典顺序比较两个字符串。
int compareToIgnoreCase(String str) 按字典顺序比较两个字符串,不考虑大小写。5.9. String intern() 返回字符串对象的规范化表示形式。
static String format(String format, Object... args) 使用指定的格式字符串和参数返回一个格式化字符串
二、StringBuffer 与 StringBuilder
StringBuffer 是字符串缓冲区 是一个容器
JKD1. 0版本之后出现
1. 特点:
1.1. 长度可变化
1.2. 可以操作多个数据类型
1.3. 可以通过toString方法变成字符串
2. 功能 (数据基本操作 C Create D Delete Update R Read )
2.1. 存储
StringBuffer append(数据) 将参数的字符串表示形式添加到此序列结尾处
StringBuffer insert(int offset, 数据) 将参数的字符串表示形式插入此序列指定位置之后。2.2. 删除
StringBuffer delete(int start, int end) 移除此序列的子字符串中(之间包含start不包含end) 的字符。
StringBuffer deleteCharAt(int index) 移除此序列指定位置的 char。2.3. 获取
2.3.1. 获取当前字符串缓冲区容量
Capacity()
2.3.2. 获取当前字符串缓冲区存放在字符个数
2.3.3. Length()
2.3.4. 通过索引获取char值
char charAt(int index) 返回此序列中指定索引处的 char 值。
2.3.5. 通过子字符串获取其位置
int indexOf(String str) 返回第一次出现的指定子字符串在该字符串中的索引。
int indexOf(String str, int fromIndex) 从指定的索引处开始,返回第一次出现的指 定子字符串在该字符串中的索引。
int lastIndexOf(String str) 返回最右边第一次出现的指定子字符串在此字符串中 的索引。
int lastIndexOf(String str, int romIndex) 返回从romIndex开始往前第一次出现 指定子字符串的索引。
2.3.6. 获取字串
String substring(int start) 返回一个新的 String,它包含此字符序列当前所包含的字 符子序列 。
String substring(int start, int end) 返回一个新的 String,它包含此序列当前所包含的 字符子序列。2.4. 替换
StringBuffer replace(int start, int end, String str) 使用给定 String 中的字符替换此序列的子字 符串中的字符。
void setCharAt(int index, char ch) 将给定索引处的字符设置为指定新字符2.5. 反转
StringBuffer reverse() 将此字符序列用其反转形式取代。
2.6. 复制和转换
2.6.1. 转换toString()将缓冲区序列用字符串表示
2.6.2. 复制void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) 将字符从此序列 复制到目标字符数组 dst。
2.7. 插入
2.7.1. 在结尾处插入,对append方法进行重载可以将基本类型(byte和short除外)字符串形式或String串或StringBuffer或Object字符串形式插入到当前StringBuffer的结尾处,String常常使用的+操作符将数据类型转换成字符串并且以此追加到String的结尾,实际是通过StringBuffer的append方法来实现的
StringBuffer append(boolean\char\int\long\double\long)
StringBuffer append(String s)
StringBuffer append(StringBuffer st)
StringBuffer append(Object o)
可以将字符数组自动转换为字符串之后追加到StringBuffer后面
StringBuffer append(cahr[] ch)
StringBuffer append(char[] ch,int offset ,int length)
2.7.2. 在指定位置插入 ,也是对insert方法的重载用法跟append差不多,只是插入位置不同
StringBuffer insert(int offset ,boolean\char\int\long\float\double)
StringBuffer append(int offset ,String s)
StringBuffer append(int offset ,StringBuffer st)
StringBuffer append(int offset ,Object o)
可以将字符数组自动转换为字符串之后插入到StringBuffer指定位置
StringBuffer append(int offset ,cahr[] ch)
StringBuffer append(int offset ,char[] ch,int offset ,int length)
JKD1.5 版本之后出现StringBuilder
StringBuffer 线程同步 安全 但效率低 建议多线程时用
StringBuilder 线程不同步 不安全 但效率高 建议单线程用
升级通常需要考虑的三个重要因素:
提高安全性
提高效率
简化书写
工具类 :方法都是静态的类, 无需new 可以直接用类名调用
常见工具类
Arrays 操作数组的工具类
Collections 操作集合的工具类
DateFormat 操作日期的工具类
Math 操作基本数值运算的工具类
三、正则表达式
通过特定符号来表示规则,用来操作字符串的字符串表达式,用regex表示
1. 字符串表达式表示为正则表达式
必须要求字符串能被编译为Pattern 模式实例
用该模式可以创建匹配器
2. 正则表达式优缺点
优点:便捷简单
缺点:阅读性查
3. 根据正则表达式对字符串的操作
3.1. 匹配 matches(String regex) 返回boolean值
3.2. 替换 replaceAll(String regex , String str ) 将符合正则的字符串替换
replaceFirst(String regex , String str )3.3. 获取 group返回符合规则的字串
3.4. 切割 split(String regex) 根据正则切割字符串返回字符串数组
4. 正则表达式构造概要
使用正则表达式时凡是正则字符含有反斜杠的如果不是在[]或()内使用都需要
加上一个反斜杠,前一个表示转义,后一个跟后面符号为正则字符
^在单独使用\^时表示行开头 在[]内使用时表示取反
字符
\t
\n
\r
\a
\e
字符类
[abc] a或b或c
[^abc] 除了a或b或c以外的所有字符
[a-z] a到z
[a-zA-Z] 字母
[a-d[m-p]]或[a-dm-p] a到d或m-p
[a-z&&[def]] 等于[def]
[a-z&&[^def] 等于[a-cg-z]
[a-z&&[^m-p] 等于[a-lq-z]
预定义字符:. 任何字符
\d [0-9]
\D [^0-9]
\s [ \t\n\x0B\f\r]
\S [^\s]
\w [a-zA-Z_0-9]
\W [^\w]边界匹配器
^ 行的开头
$ 行的结尾
\b 单词边界
\B 非单词边界
\A 输入的开头
\G 上一个匹配的结尾
\Z 输入的结尾,仅用于最后的结束符(如果有的话)
\z 输入的结尾数量限定
? 0或1次
* 0或1次以上
+ 1或1次以上
{n} n 次
{n,} n次以上
{n,m} n次到m次捕获组
(X) 复合使用时 有几个左括号就有几组 ,组的编号从左括号自左到右顺序排
组引用
\n 组的引用(编号)
(X)\\n表示与编号为n的组(X)匹配
5. 正则表达式内部将规则封装为类 即 java.util.regex包中的 Pattern
Pattern 是正则表达式的编译表示形式
字符串的正则表达式必须首先被编译为此类的实例
Pattern 类中没有对象特有的属性 所以没有构造函数 可以通过静态方法 compile 返回一个 Pattern 对象5.1. public static Pattern compile(String regex) 将给定的正则表达式编译到模式中。
5.1.1. 将正则表达式封装成对象
5.1.2. 让正则对象和要操作的字符串相关联
5.1.3. 关联后获取匹配正则匹配引擎
5.1.4. 通过引擎对符合规则的子串进行操
String str = "aaaaab" ;
String regex = "a*b" ;
Pattern p = Pattern.compile(regex); //将正则表达式封装成对象
Matcher m = p.matcher(str); //让正则对象和要操作的字符串相关联 获取匹配器
boolean b = m.matches();//在仅使用一次正则表达式时,可以方便地通过此类定义 matches 方法。以上三句等效于以下一句
boolean b = Pattern.matches(regex, str);String 类中的matches 方法就是用 Pattern 和 Matcher 方法实现的 String的matches 功能比 较单一 ,
若想要实现复杂的匹配操作则需要由以上的方法实现
String 中的 matches方法 replaceAll , replaceFirst方法 split 方法分别对以下方法进行封装实现
Matcher 的方法
boolean matches()
replaceAll(String str )
replaceFirst(String str)
Pattern 的方法
static boolean matches(String regex, CharSequence input)
编译给定正则表达式并尝试将给定输入与其匹配
Pattern.matches(regex, input);
等效于 Pattern.compile(regex).matcher(input).matches()
public String[] split(CharSequence input)
public String[] split(CharSequence input, int limit)
6. String 用到正则表达式的方法
6.1. 匹配方法
public boolean matches(String regex) {
/*以下语句等效于 Pattern.compile(regex).matcher(input).matches() ,这里的matches方法是 Matcher的方法*/
return Pattern.matches(regex, this);//这里的matches方法是Pattern中的静态方法
}
6.2. 替换方法
6.2.1. public String replaceFirst(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceFirst(replacement);
}6.2.2. public String replaceAll(String regex, String replacement) {
return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}//String 是 Charsequence 的子类,所以使用方法跟上面的相同6.2.3. public String replace(CharSequence target, CharSequence replacement) {
return Pattern.compile(target.toString(), Pattern.LITERAL).matcher(
this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
}6.3. 切割方法
6.3.1. public String[] split(String regex, int limit) {
/*String 中的split方法第一个参数是 regex 而 Pattern 中的split 第一个参数是要拆分字符序列*/
return Pattern.compile(regex).split(this, limit);
}Limit是限制匹配次数的
字符串 "boo:and:foo" 使用这些参数可生成以下结果:
Regex Limit 结果
: 2 { "boo", "and:foo" }
: 5 { "boo", "and", "foo" }
: -2 { "boo", "and", "foo" }
o 5 { "b", "", ":and:f", "", "" }
o -2 { "b", "", ":and:f", "", "" }
o 0 { "b", "", ":and:f" }
如果 n 为正数 , 则模式将被最多应用 n - 1 次,数组的长度将不会大于 n,而且数组的最后一项将包含所有超出最后匹配的定界符的输入。
如果 n 为非正,那么模式将被应用尽可能多的次数,而且数组可以是任何长度。
如果 n 为 0,那么模式将被应用尽可能多的次数,数组可以是任何长度,并且结尾空字符串将被丢弃。6.3.2. public String[] split(String regex) {
return split(regex, 0);
}str.split(regex, n) 等效于
Pattern.compile(regex).split(str, n)根据正则表达式获取字符串中的子串
1,用 Pattern 的静态方法compile编译正则表达式
2,调用 Pattern 的方法matcher获取匹配器
3,用匹配器的find方法查找符合正则表达式的子串,如果符合规则则返回true
4,用匹配器的group方法捕获匹配的字串find方法找到匹配字串后可以用 start end 和group方法来获取匹配字串
start 是匹配字串的左索引
end 是匹配字串的右索引的下一个索引
捕获组是从 1 开始从左到右的索引。组零表示整个模式,因此m.find(0)等效于 m.find()
m.start(0)等效于 m.start()
m.end(0) 等效于m.end()
m.group(0) 等效于 m.group()。
匹配器 m、输入序列 str 和组索引 g,表达式 m.group(g) 和 str.substring(m.start(g), m.end(g)) 是等效的。