文章目录
1.String类
String 概述:
String:字符串,使用一对" "引起来表示
1.String声明为final的,不可被继承
2.String实现了Serializable接口:表示字符串是支持序列化的
实现了Comparable接口:表示String可以比较大小
3.String内部定义了final char[] value 用于存储字符串数据
4.String:代表不可变的字符序列;不可变性
5.通过字面量的方式(区别于new给一个字符串赋值,此时的字符串值声明在字符串常量池中)。
6.字符串常量池中是不会存储相同内容(使用String类的equals()比较,返回true)的字符串的
String不可变性的说明:
1.当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。
2.当对现的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
3.当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值。
源码:
public final class String
implements java.io.Serializable, Comparable <String>, CharSequence {
private final char value[];
String实例化的方式:
方式一:通过字面量实例化 :String s=“qw”; 此时的s的数据“qw”声明在方法区中的字符串常量池中;
方式二:通过new 的方式实例化 :String s=new String(“qw”);此时s所保存的地址是在堆空间中开辟之后对应的地址值;
面试题:String p =new String(“abc”);此方式创建对象,问内存中创建了几个对象?
两个:一个是堆空间中new的结构。另一个是char[]对应的在常量池中的数据"abc";
两种实例化方式在内存中的位置不同
String s="java";
String s1="java";
String p=new String("java");
String p1=new String ("java");
System.out.println(s==s1);//true
System.out.println(s==p);//false
System.out.println(s==p1);//false
System.out.println(p==p1);//false
为何会出现上述的结果
new的结构存储在堆空间中,String str=“name”;以此方式实例化存储在常量池中,new方式实例化,它引用的地址,也指向常量池中,引用地址的不同
final 常量
结论:1.常量与常量的拼接在常量池,且常量池中不会存在相同的常量;
2.只要其中有一个是变量,结果就在堆中;
3.如果拼接的结果调用intern()方法,返回值就在常量池中;
String 与其他类型的转换
String 与数据类型,包装类的转换
包装类–>String 类型 调用包装类的parsexxx(str)
String–>包装类 调用String的ValueOf(XXX)
String s="123";
int i = Integer.parseInt(s);
System.out.println(i);
String s1 = String.valueOf(i);
String s2=i+"";
System.out.println(s1);
System.out.println(s2);
String 与char[]之间的转换
String–>char[] 调用String的toCharArray()方法
char[] -->String 调用String的构造器
String s="hello";
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
System.out.println(chars[i]);
}
char[] p=new char[]{'j','a','v','a'};
String s1 = new String(p);
System.out.println(s1);
String 与byte[]之间的转换
编码 String–>byte[] 调用String的getBytes()方法
解码 byte[] -->String 调用String的构造器
编码: 字符串–>字节 (看的懂的–>看不懂的二进制数据)
解码: 编码的逆过程 字节–>字符串 (看不懂的二进制数据–>看的懂的字符串)
- 说明:解码时,要求使用的字符集必须与编码时使用的字符集一致,否则会出现乱码;
String s="abc中国";
byte[] bytes = s.getBytes();//使用默认编码集
System.out.println(Arrays.toString(bytes));
byte[] gbks = s.getBytes("gbk");//使用gbk编码集
System.out.println(Arrays.toString(gbks));
System.out.println("*****************");
String s1 = new String(bytes);//使用默认的解码集
System.out.println(s1);
String s2 = new String(gbks);//乱码 编码集不一致
System.out.println(s2);
String gbk = new String(gbks, "gbk");//使用gbk解码集
System.out.println(gbk);
2.String 的常用方法
1.int length():返回字符串的长度: return value.length
2.char charAt(int index): 返回某索引处的字符return value[index]
3.boolean isEmpty():判断是否是空字符串:
return value.length == 0
4.String toLowerCase():使用默认语言环境,将 String 中的所字符转换为小写
5.String toUpperCase():使用默认语言环境,将 String 中的所字符转换为大写
6.String trim():返回字符串的副本,忽略前导空白和尾部空白
7.boolean equals(Object obj):比较字符串的内容是否相同
8.boolean equalsIgnoreCase(String anotherString):与equals方法类似,忽略大小写
9.String concat(String str):将指定字符串连接到此字符串的结尾。 等价于用“+”
10.int compareTo(String anotherString):比较两个字符串的大小
11.String substring(int beginIndex):返回一个新的字符串,它是此字符串的从beginIndex开始截取到最后的一个子字符串。
12.String substring(int beginIndex, int endIndex) :返回一个新字符串,它是此字符串从beginIndex开始截取到endIndex(不包含)的一个子字符串。
13.boolean endsWith(String suffix):测试此字符串是否以指定的后缀结束
14.boolean startsWith(String prefix):测试此字符串是否以指定的前缀开始
15.boolean startsWith(String prefix, int toffset):测试此字符串从指定索引开始的子字符串是否以指定前缀开始
16.boolean contains(CharSequence s):当且仅当此字符串包含指定的 char 值序列时,返回 true
17.int indexOf(String str):返回指定子字符串在此字符串中第一次出现处的索引
18.int indexOf(String str, int fromIndex):返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始
19.int lastIndexOf(String str):返回指定子字符串在此字符串中最右边出现处的索引
20.int lastIndexOf(String str, int fromIndex):返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始反向搜索
-
注:indexOf和lastIndexOf方法如果未找到都是返回-1
-
替换:
String replace(char oldChar, char newChar):返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所 oldChar 得到的。
String replace(CharSequence target, CharSequence replacement):使用指定的字面值替换序列替换此字符串所匹配字面值目标序列的子字符串。
String replaceAll(String regex, String replacement):使用给定的 >
replacement 替换此字符串所匹配给定的正则表达式的子字符串。
String replaceFirst(String regex, String replacement):使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。
3.关于StringBuffer 和StringBuilder的使用
*说明:StringBuffer和StringBuider只存在线程是否安全的不同,底层源码相同
源码分析:
- String str=new String();//char[] value=new char[0];
- String str1=new String(“abc”);//char[] value=new char[]{ ‘a’,‘b’,‘c’};
- StringBuffer s=new StringBuffer();//char[] value=new char[16];底层创建了一个长度为16的数组
- 源码:
public StringBuffer(String str) {
* super(str.length() + 16);
* append(str);
* }
添加数组元素的方式: s.append(‘a’);//value[0]=‘a’;
- StringBuffer s=new StringBuffer(“abc”);//
char[] value=new char[“abc”.length()+16]; - 问题一: System.out.println(s.length());//3
- 问题二:扩容问题,如果存入的数据底层数组容纳不下,那就需要扩容底层的数组
- 扩容方式: 默认为扩容为原来容量的 2倍 +2 ,同时将原有数组的元素复制到新的数组中
意义:开发中建议使用 StringBuffer(int capacity)或StringBuilder(int capacity) 避免扩容
- String,StringBuffer,StringBuilder的 执行效率?
StringBuilder>StringBuffer>String
String 与StringBuffer,StringBuilder之间的转换
String -->StringBuilder,StringBuffer 调用StringBuilder,StringBuffer的构造器
StringBuilder,StringBuffer–>String
①调用String的构造器 ②StringBuilder,StringBuffer 的toString()方法
String,StringBuffer,StringBuilder的异同?
String:不可变的字符序列;底层是char[] value数组存储
StringBuffer:可变的字符序列; 线程安全的,效率低;底层是char[] value数组存储
StringBuilder:可变的字符序列;线程不安全的,效率高;底层是char[] value数组存储