String
java.lang. String是字符串
特性:
它底层是一个字符数组,所以它有很多特性就是数组特性
- 字符串一旦被创建,这个字符串对象就不能更改
- 为了提升字符串访问效率,Java虚拟机采用了一种缓存的技术,虽然String是引用数据类型(类),但字符串对象都会在静态区有一个字符串常量池
- 程序执行中,如果程序要用到字符串,虚拟机首先会在常量池中搜索,有,就直接指向这个字符串;没有,就创建一个,再指向它
注意:
- 因为整形常量池的存在,所以不要频繁的去拼接字符串,因为那会不停的创建字符串对象,浪费空间。
- 并不是都是直接通过整形常量池创建字符串,保存的是常量池内的数据地址;当你new的时候,这个会通过堆内存在在常量池创建对象,保存的是堆内存地址,而堆内存会指向常量池地址。所以在比较时,用equals去判断是否相等,而不能是==,我们大多数比较用的都是equals,这会增加系统的鲁棒性 (健壮性)。
String s1="abc";
// 重新赋值并不是覆盖,只是搜索,有,就指向s1,没有就创建一个,指向它,引用地址改变
// s1是main方法中局部变量,并且没有使用final修饰,所以可以更改s1的值
// 因为s1只是保存了一个内存地址,所以s1可以重新赋值一个新的内存地址
// 但是 abc对象,更改不了了,
// s1="def";
String s2="abc";
String s3="Abc";
//new 了就是要通过堆 ,然后最终指向字符串对象,没有new就是直接指向字符串对象,保存的引用地址不一样
String s4=new String("abc");
String s5=new String("abc");
// 首先==引用数据类型里面比较的是地址
System.out.println(s1==s2);//true
//大小写不同自然指向的不是一个对象
System.out.println(s2==s3);//false
System.out.println(s2==s4);//false
System.out.println(s4==s5);//false
// equals 最终比较的是值,我们大多数用这种比较,增加系统的鲁棒性
System.out.println(s1.equals(s2));
操作与常用方法:
** 数组化字符串**
// 3 传递字节数组 转换为字符串
byte[] bytes= {97,98,99};
String s3=new String(bytes);
System.out.println(s3);
// 截取字节数组中的一部分 下面即表示下标1开始(包含)取2个
String s4=new String(bytes,1,2);
System.out.println(s4);
// 传递字符数组,转换为字符串
char[] chars= {'q','w','e','r'};
String s5=new String(chars);
System.out.println(s5);
// 截取字符数组一部分 规则如上
String s6=new String(chars,0,2);
System.out.println(s6);
//结果:abc
// bc
// qwer
// qw
常用方法
// 1 char型 charAt(int index) 获取字符中,一个位置上的字符,相当于arr[index]
String s1="qwer";
char c1=s1.charAt(2);
System.out.println(c1);
// 2 boolean endsWith(String suffix) 判断字符串字符以指定字符串结尾
// startWith(String prefix) 判断开始
System.out.println("hello.java".endsWith(".java"));
// 一定要注意空格
// 3 boolean equalsIgnoreCase(String anotherString) 不区分大小写比较两个字符串是否相等
System.out.println("abc".equalsIgnoreCase("ABC"));
// 4 byre[] getBytes(); 把字符串转换为字节数组
byte[] bytes ="abc".getBytes();
for(byte b:bytes) {
System.out.println(b);
}
// 5 int indexOf(String str) 获取指定字符串的 起始 索引,找不到就返回-1
System.out.println("dajfjahfahdhajfhasjd".indexOf("fj")); // 3下标
// int indexOf(String str,int fromIndex) 从指定位置开始查找,找不到返回-1
System.out.println("dajfjahfahdhajfhasfjd".indexOf("fj",9)); // 18下标
// int lastIndexOf(String str) 最后 一次出现位置的索引,找不到返回-1
System.out.println("dajfjah".lastIndexOf("a")); // 5下标
// 6 int length() 获取字符串长度
System.out.println("ddfa".length()); // 4
// 7 String replaceAll(String regex,String replacement) 把指定字符串换位指定字符replace加上All是支持正则表达式,不加不支持,也能用
System.out.println("-------------"+"12h,dhasa'f'd'sh@#3!23><".replaceAll("[^0-9]",",")); //12,,,,,,,,,,,,,,,,3,23,,
// 8 String[] split(String regix) 分割字符串,需要指定分隔符,返回值是字符串数组,支持正则表达式
String myTime ="2020,07,14";
String[] ymd=myTime.split(",");
for(String string:ymd) {
System.out.println(string);
}
// 注意如果分割符是.那么得写成\\. 因为.在正则表达式有特殊意义,需要转义然后Java也再转义一次
// 9 String substring(int begin) 获取该字符串以一个下标开始的字符串(包含)
System.out.println("ajfklhajask".substring(2)); // fklhajask
//以一个下标开始(包含)到另一个下标结束 (不包含)
System.out.println("ajfklhajask".substring(2,7)); // fklha
// 10 char[] toCharArray() 转换为char数组
char[] c2="skfjsh".toCharArray();
for(char c :c2) {
System.out.println(c);
}
// 11 转大写和转小写
System.out.println("ajfdkf".toUpperCase());
System.out.println("ajfdkf".toLowerCase());
// 12 String trim() 去除字符串首尾的空格
System.out.println(" 23 dfjh ".trim());
StringBuffer与StringBuilder
原理:
预先在内存中申请一块空间,用来容纳字符序列(字符数组)
如果预留空间不够,会自动扩容 默认初始化容量为16个字符
区别:
- StringBuffer是线程安全,在多线程环境下使用,不会出现问题,所以常用于类中。
- StringBuilder是非线程安全,在多线程环境下使用,可能出现问题,所以常用在方法中。
所以:
在不考虑安全性的情况下,StringBuilder运行效率高,用的也比较多
与String的区别:
- String是不可变的字符序列,存储在字符串常量池
- StringBuffer和StringBuilder是可变的,底层也是char数组,并且可以自动扩容
String[] arr= {"a","b","c"};
StringBuilder sb=new StringBuilder();
for(String string:arr) {
//用于存储
sb.append(string);
}
System.out.println(sb);
// 调用toString方法,转换为String类型
String string =sb.toString();
System.out.println(string);