String 类
-
String声明为final ,不可以被继承
-
String 实现了Serializable接口,表明字符串是可序列化的
-
String 实现了Compareble接口,表示String 可比较大小
-
String 内部定义了 final char[] value value用于存储字符串数据,表明了不可变的字符特性 ---- 1.当对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值。2.当对现有的字符串进行连接操作时,也需要重新指定内存区域赋值。3.当调用String 的 replace 方法修改指定的字符或字符串时,也需要重新指定内存区域赋值。
-
通过字面量的方式(区别new)去给字符串赋值,此时字符串值声明在字符串常量池中,常量池中是不会存储相同内容的字符串的。
package StringTT;
import org.junit.Test;
public class Stringlei {
@Test public void test1(){ String s1 = "abc"; // 字面量的定义方式 String s2 = "abc"; System.out.println(s1 == s2); // 对象比较的是地址值 s1 = "hello"; System.out.println(s1); System.out.println(s2); System.out.println("*****************"); String s3 = "abc"; s3 += "def" ; System.out.println(s3); }
}
创建String对象
new 是在堆空间中创建
String s = new String(“abc”); 方式创建对象,在内存中创建了几个对象?两个:一个是堆空间new的结构,另一个是char[]对象常量池中的数据:“abc”
package StringTT;
import org.junit.Test;
public class StringTest2 {
@Test
public void test(){
//方式一:通过字面量定义
String s1 = "javaEE";
String s2 = "javaEE";
// 方式二:用new 在堆空间中创建
String s3 = new String("javaEE");
String s4 = new String("javaEE");
System.out.println(s1 == s2); // true
System.out.println(s3 == s4); // false
}
}
常量与常量的拼接结果在常量词中,常量与变量拼接,结果就会在堆当中
@Test
public void test1(){
String s1 = "javaEE";
String s2 = "hadoop";
String s3 = "javaEEhadoop";
String s4 = "javaEE" + "hadoop";
String s5 = s1 + "hadoop";
String s6 = "javaEE" + s2;
String s7 = s1 + s2;
System.out.println(s3 == s4); // true
System.out.println(s3 == s5); // false
System.out.println(s3 == s6); // false
System.out.println(s3 == s7); // false
System.out.println(s5 == s4); // fasle
System.out.println(s5 == s6); // fasle
System.out.println(s5 == s7); // fasle
String s8 = s5.intern(); // 得到的是在常量池
System.out.println(s8 == s3); // true
}
String 方法
String 和 char[] 的转换
-
String 转 char[] 用 String.toCharArray()方法
-
char[] 转 String 调用String 的构造器
package StringTT;
import org.junit.Test;
public class StringTest1 {
// String 和 byte的转换
@Test
public void test123(){
String str1 = “abc123”;
char[] charArray = str1.toCharArray();
for (int i = 0;i < 100; i++){
System.out.println(charArray[i]);
}
}@Test public void test2(){ char[] ch1 = new char[]{'h','e','l','l','o'}; String str2 = new String(ch1); System.out.println(str2); }
}
String 和 byte[] 的转换
有中文的话就转不了一个数字了
编码 :字符串 --> 字节 (看得懂 -->看不懂)String 转 byte[] 用String的getBytes()方法
解码:字节 – > 字符串(看不懂的二进制 – > 看得懂)byte[] --> String
解码过程中,必须与编码所使用的字符集一致
package StringTT;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import org.junit.Test;
public class StringTest1 {
// String 和 byte的转换
@Test
public void test123(){
String str1 = "abc123";
char[] charArray = str1.toCharArray();
for (int i = 0;i < str1.length(); i++){
System.out.println(charArray[i]);
}
}
@Test
public void test2(){
char[] ch1 = new char[]{'h','e','l','l','o'};
String str2 = new String(ch1);
System.out.println(str2);
}
@Test
public void test3() throws UnsupportedEncodingException{
String str1 = "abc123中国";
byte[] b1 = str1.getBytes(); // 使用默认的字符集进行转换
System.out.println(Arrays.toString(b1)); //输出
byte[] b2 = str1.getBytes("gbk"); //使用gbk字符集进行编码
System.out.println(Arrays.toString(b2));
//解码 byte[] --> String
String s1 = new String(b1); // 默认的字符集进行解码
System.out.println(s1);
}
}
StringBuffer 、StringBuilder、String 异同
- String 不可变的字符序列,底层用char[]进行存储
- StringBuffer 可变的字符序列,线程安全的,效率偏低,底层用char[]进行存储
- StringBuilder 可变的字符序列,JDK5.0新增,线程不安全,效率高,底层用char[]进行存储
源码分析
String str = new String();//char[] value = new char[0];
String str = new String(“abc”); // char[] value = new char[]{‘a’,‘b’,‘c’};
StringBuffer str = new StringBuffer();//char[] value = new char[16]; 底层创建了一个长度是16的字符数组
StringBuffer str1 = new StringBuffer(“abc”); // char[] value = new char(“abc”.length + 16) 创建了长度为19的字符数组
问题1:打印str1的长度是多少呢?还是3
问题2:如果要添加的数据,底层数据盛不下了,那就需要扩容底层的数组。默认情况下,扩容为原来容量的两倍+2,同时将原有数组的元素复制到新数组中
指导意义:开发中建议使用StringBuffer(int capacity) 或 StringBuilder(int capacity) ,就看需不需要考虑安全
package StringTT;
import org.junit.Test;
public class StringBufferBuiderTest {
@Test
public void test(){
StringBuffer sb1 = new StringBuffer("abc");
sb1.setCharAt(0, 'm');
System.out.println(sb1);
String s1 = "abc";
s1.replace('a','m');
System.out.println(s1); //s1不变
}
}
public String substring – 返回一个start 开始 end索引结束的左闭右开区间的子字符串
效率从高到低排列:StringBuilder > StringBuffer > String
JDK8.0之前 日期和时间API
@Test
public void test(){
long time = System.currentTimeMillis();
System.out.println(time); //1970/1/1 到我们现在的时间差 毫秒数,通常叫一个时间戳
}