一、java.lang.String类
1.String类的描述
(1)String累的代表字符串
(2)java程序中的所有字符串字面值都作为此类的实例实现
""它是字符串的对象
“hello”他也是字符串的对象
(3)字符串是常量:他们的值在创建之后不能更改。
字符串对象不可变,一旦修改某个字符串,就会产生新的字符串对象
(4)字符串缓冲区支持可变的字符串
字符串缓冲区:StringBuffer和StringBuilder类型 对象支持可变的字符串。
(5)String类型是常量,所以可以共享
(6)字符串底层用char数组表示。
2.String类的特点
(1)String类型是final声明,不能被继承
(2)String对象内部使用字符串数组char[]进行保存
java9内部用byte[]保存:节省空间
“hello” ={‘h’,‘e’,‘l’,‘l’,‘o’}char数组
(3)String类的对象不可变
核心类库怎么做到的?
private final char value[];
final意味着value数组的地址不能变,不能通过扩容等方式指向新的数组
String类中所有涉及到修改字符串的方法,例如:reolace等,如果修改字符串的字符内容,都是用新的字符串对象返回的
(4)字符串对象不可变,字符串常量可以共享,储存在常量池中
常量池在方法区里
常量池中的字符串对象时共享,即两个内容一致的字符串常量是同一个对象
3.字符串对象的创建
(1)字符串常量对象
(2)我们自己new,用构造器
String()
String(char[])
String(char[] value, int offset, int length)
String(byte[])
String(byte[] value, int offset, int length)
String(String)
在堆里
(3)String类静态方法valueOf()
在堆里
(4)+拼接的结果
有在堆里,有在常量池
4.字符串的拼接问题
(1)指向常量池中的字符串常量 + 指向常量池中的字符串常量 结果在常量池
其他都是堆
其他的:
指向常量池中的字符串常量 + 变量
变量 + 变量
指向堆中的字符串(变量、常量) + xxx
(2)字符串xx.intern()结果一定在常量池
(3)拼接的实现
(1)+
(2)concat(xx)
7.字符串的比较
(1)==比较的是地址
(2)equals比较的内容,严格区分大小写
(3)equalsIgnoreCase(String anotherString):比较内容部分大小写
(4)compareTo,区分大小写
(5)caompareToIgnoreCase,不区分大小写
(6)常量于变量比较,把常量写前边
只有包装类和字符串可以直接等于xxxx
其他都得new
8、空字符串
(1)如何理解空字符串?
问?空字符串有对象吗? 有
问?空字符串的特点? 有对象,其次,字符串的长度为0
(2)如何判断某个字符串是否是空字符串
①借助length() if(str != null && str.length()==)
②借助equals() if("".equals(str))
③借助isEmpty() if(str != null && str.isEmpty())
提示:字符串的长度:字符串.length() 有()是方法
数组的长度:数组名.length 没有()是属性,
9、字符串的方法们
(1)boolean isEmpty():字符串是否为空
(2)int length():返回字符串的长度
(3)String concat(xx):拼接,等价于+
(4)boolean equals(Object obj):比较字符串是否相等,区分大小写
(5)boolean equalsIgnoreCase(Object obj):比较字符串是否相等,区分大小写
(6)int compareTo(String other):比较字符串大小,区分大小写,按照Unicode编码值比较大小
(7)int compareToIgnoreCase(String other):比较字符串大小,不区分大小写
(8)String toLowerCase():将字符串中大写字母转为小写
(9)String toUpperCase():将字符串中小写字母转为大写
(10)String trim():去掉字符串前后空白符,不包括中间的空白符
(二)系列2:查找等方法
(1)boolean contains(xx):是否包含xx
(2)int indexOf(xx):返回第一次出现的下标
(3)int lastIndexOf(xx):返回最后一次出现的下标
(三)字符串的截取
(1)public String substring(int beginIndex):说明截取当前字符串[beginIndex]到最后
(2)public String substring(int beginIndex, int endIndex):说明截取当前字符串[beginIndex, endIndex)
(四)系列4:和字符相关
(1)获取某个[index]的char
因为String的底层是char[],所以可以获取某个下标位置的char
(2)char[] toCharArray()
(3)new String(char[])
new String(char[], int , int)
(4)String.valueOf(char[])
(五)和字节相关的方法
(1)byte[] getBytes():使用平台的默认字符集将此 String 编码为 byte 序列
(2)byte[] getBytes(Charset charset)
byte[] getBytes(String charsetName)
ASCII表范围内的都是1个字节,无论是什么编码,所有编码都兼容ASCII表
GBK:汉字是2个字节
UTF-8:常见的汉字是3个字节
ISO8859-1:不支持中文,每一个字符用1个字节
(3)String(byte[]):使用平台的默认字符集讲byte序列转为字符串
(4)String(byte[] data, Charset charset)
String(byte[] data, String charsetName)
字符串 -- > 字节数组 编码(编为计算机认识的字节二进制值)
字节数组 --> 字符串 解码(解为人能看懂的字符值)
什么情况会发生乱码?
(1)编码与解码的字符集对不上
(2)缺了,或多了字节也会乱码
(六)判断字符串是否以xx开头或xx结尾
(1)boolean startsWith(xx)
(2)boolean endsWith(xx)
(七)支持正则匹配
正则:不是Java语言的东西,是独立于所有编程语言的一种语法规范。
正则表达式:匹配文本的规则的表达式。规则:
例如:是否文本中的所有字符都是数字
是否文本中的所有字母都是大写
是否文本中一共有6个字符组成,并且只有大写、小写、数字组成
…
(28)boolean matches(正则表达式):判断当前字符串是否匹配某个正则表达式
(八)字符串的替换
(1)String replace(xx,yy):把字符串中的xx替换为yy
(2)String replaceFirst(xx,yy):把第一个符号的xx,替换为yy
(3)String replaceAll(xx,yy):把所有的xx替换为yy
replace与replaceAll的区别?
replace:不支持正则,原样匹配替换
replaceAll:支持正则,可以把匹配正则的部分替换掉
(九)拆分
public String[] split(String regex):把一个字符串按照某种规则拆分为多个字符串
总结一下支持正则的方法:
(1)matches(xx)
(2)replaceFirst(xx,yy)和replaceAll(xx,yy)
(3)split(xx)
xx表示正则
二、可变字符序列
1、String与可变字符序列的异同点:
相同点:他们都是表示字符序列,即一串字符
不同点:String表示的是不可变的字符序列,一旦创建就不能修改,一旦修改就产生新对象
可变字符序列表示的是可变的字符序列,可以在原对象上对字符的内容和长度做修改。
2、可变字符序列的代表:StringBuffer和StringBuilder,都在java.lang包
StringBuffer和StringBuilder这两个类的API几乎是一模一样,即方法是一样,功能是一样。
区别:
StringBuffer:旧点(JDK1.0),线程安全的,相对来说效率低
StringBuilder:新点(JDK1.5),线程不安全的,相对来说效率高
3、API(以StringBuilder为例,StringBuffer一样,就是类型换一下)
(1)StringBuilder append(xx):追加
(2)public StringBuilder delete(int start,int end)
public StringBuilder deleteCharAt(int index)
(3)public StringBuilder insert(int offset,xx)
(4)public StringBuilder reverse():反转
…
4、看源码
(1)StringBuffer线程安全,和StringBuilder不安全
StringBuffer关于字符序列修改的方法都有synchronized修饰。
(2)如何可变
所有的操作都是在原来的value数组中进行操作。
如果value的长度不够,会扩容,让value指向新的数组,但是StringBuffer和StringBuilder对象的地址没有改变
5、看效率
三、泛型
1,什么是泛型
<类型>或等都是泛型
2.为什么使用泛型
(1)避免强制类型转换
(2)安全,可以在编译时避免甚多类型不符合的问题
3.泛型的由来
启发:标签
启发:方法的形参
类型未知,把类型当做参数来传递
4.如何使用
(1)声明泛型
…
单个的大写字母代表一个位置的类型
(2)泛型的使用
public class TestGeneric {
@Test
public void test01(){
StudentNameComparator s = new StudentNameComparator();
// s.compare("张三","李四");//如果没有泛型有风险,运行时才发现,有泛型,编译时就可以发现
}
}
class Student implements Comparable<Student>{
private String name;
private int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", score=" + score +
'}';
}
@Override
public int compareTo(Student o) {
return this.score - o.score;
}
/*@Override
public int compareTo(Object o) {
//按照成绩比较大小
Student stu = (Student) o;
return this.score - stu.score;
}*/
}
5.语法
(1).泛型类或者泛型接口
(2)泛型方法
6.方形类与接口
1.声明
【修饰符】class 类名<泛型>{
}
【修饰符】interface 类型<泛型>{
}
注意:(1)申明泛型是,强烈建议大家使用单个的大写字母代表未知的类型
2.使用
(1)创建对象时使用
(2)在继承和实现的时候指定类型
注意
(1)不能是基本数据类型,必须是引用数据类型
如果是基本数类型,使用包装类
(2)类或者接口不能用于静态成员(方法、成员)
(3)泛型类如果指定了上限,既不能超过其上限
补充:
java.text.Collator:Collator 类执行区分语言环境的 String 比较。使用此类可为自然语言文本构建搜索和排序例程。
Collator是一个抽象类,我们要么new子类对象,要么
public static Collator getInstance()
public static Collator getInstance(Locale desiredLocale)