String类源码学习
一、初始String类:
- String类是final类型的,表示该类不能被继承。如下图所示:
- 这是一个字符数组,且是final的,用于存储字符串的内容。
本质:String是用char[ ]实现的。
/** The value is used for character storage. */
private final char value[];
<blockquote><pre>
* String str = "abc";
* </pre></blockquote><p>
* is equivalent to:
* <blockquote><pre>
* char data[] = {'a', 'b', 'c'};
* String str = new String(data);
- 因为String实现了Serializable接口,所以支持序列化和反序列化。Java的序列化机制是通过在运行时判断类的
serialVersionUID
来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID
与本地相应实体(类)的serialVersionUID
进行比较,如果相同就认为是一致的,可以反序列化,否则会出现序列化版本不一致的异常(InvalidCastException)。
/** use serialVersionUID from JDK 1.0.2 for interoperability */
private static final long serialVersionUID = -6849794470754667710L;
/**
* Class String is special cased within the Serialization Stream Protocol.
*
* A String instance is written into an ObjectOutputStream according to
* <a href="{@docRoot}/../platform/serialization/spec/output.html">
* Object Serialization Specification, Section 6.2, "Stream Elements"</a>
*/
private static final ObjectStreamField[] serialPersistentFields =
new ObjectStreamField[0];
二、构造方法:
String的底层是由char[ ]实现的:通过一个char[]类型的value属性。
- 使用字符数组、字符串构造一个String
/**
* Allocates a new {@code String} so that it represents the sequence of
* characters currently contained in the character array argument. The
* contents of the character array are copied; subsequent modification of
* the character array does not affect the newly created string.
*
* @param value
* The initial value of the string
*/
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length);
}
- 使用字节数组构造一个String:
public String(byte bytes[], Charset charset) {
this(bytes, 0, bytes.length, charset);
}
- 使用StringBuffer和StringBuilder 构造一个String
/**
* Allocates a new string that contains the sequence of characters
* currently contained in the string buffer argument. The contents of the
* string buffer are copied; subsequent modification of the string buffer
* does not affect the newly created string.
*
* @param buffer
* A {@code StringBuffer}
*/
public String(StringBuffer buffer) {
synchronized(buffer) {
this.value = Arrays.copyOf(buffer.getValue(), buffer.length());
}
}
/**
* Allocates a new string that contains the sequence of characters
* currently contained in the string builder argument. The contents of the
* string builder are copied; subsequent modification of the string builder
* does not affect the newly created string.
*
* <p> This constructor is provided to ease migration to {@code
* StringBuilder}. Obtaining a string from a string builder via the {@code
* toString} method is likely to run faster and is generally preferred.
*
* @param builder
* A {@code StringBuilder}
*
* @since 1.5
*/
public String(StringBuilder builder) {
this.value = Arrays.copyOf(builder.getValue(), builder.length());
}
三、String 中常用的方法:
/*String a = "abc";//放在常量池里面
String b = "abc";
String c = new String("abc");//在对内存开辟空间
System.out.println(a == b);//true
System.out.println(a == c);//false
*/
//测试String_StringBuilder_StringBuffer速度:
long start = System.currentTimeMillis();
//String s ="abc" + "de";// 等同于 String s ="abcde";
String s1 = "abc";
s1 += "de";
//StringBuffer sb = new StringBuffer().append("abc").append("de");
//StringBuilder sdr = new StringBuilder().append("abc").append("de");
long end = System.currentTimeMillis();
System.out.println(end - start) ;
//String类中常用的方法:
String str = new String(" wuxia is Perfect....");
System.out.println(str.length());//1.返回字符串的长度
System.out.println(str.isEmpty());//2.判断是否为空
System.out.println(str.substring(1, 4));//3.左闭右开,返回子串
System.out.println(str.charAt(2));//4.返回下标为2的字符
System.out.println(str.toUpperCase());//5.转大写
System.out.println(str.toLowerCase());//6.转小写
System.out.println(str.trim());//7.去掉两端空格,注意中间的没有去掉
char[] cha = str.toCharArray();//8.转为 字符数组 char[]
System.out.print("转为数组:[");
for(int i = 0;i < cha.length ; i ++) {
if(i == cha.length - 1) {
System.out.print(cha[i]+"]");
}else {
System.out.print(cha[i] +",");
}
}
System.out.println();
System.out.println(str.concat("专业有可能骗人,但是认知和格局是不会骗人的!"));//9.拼接字符串
System.out.println(str.replace("...", "!!!"));//10.替换字符串
System.out.println(str.contains("w"));//11.判断是否包含某个字符串
System.out.println(str.matches("."));//12.是否匹配给定的正则表达式
String[] strs = str.split(" ");//13.按照字符分成分割,返回String数组
System.out.print("转为数组:[");
for(int i = 0;i < strs.length ; i ++) {
if(i == strs.length - 1) {
System.out.print(strs[i]+"]");
}else {
System.out.print(strs[i] +"|");
}
}
System.out.println();
String str1 = "ABC";
byte[] bytes = str1.getBytes();//14.将字符串转成字节数组
for(int i = 0;i < bytes.length ; i ++) {
if(i == bytes.length - 1) {
System.out.print(bytes[i]+"]");
}else {
System.out.print(bytes[i] +"|");
}
}
System.out.println();
System.out.println(str1.equals("你好,吴霞"));//15.
System.out.println(str1.contentEquals(new StringBuffer("你好,吴霞")));
System.out.println(str1.equalsIgnoreCase("abc"));
System.out.println(str1.compareTo("abc"));
System.out.println(str1.compareToIgnoreCase("abc"));
System.out.println(str1.regionMatches(1, "c", 1, 1));
System.out.println(str1.substring(1));//重新new 了 一个String 避免了内存泄露,但牺牲了性能
System.out.println(str1.replaceFirst("A", "吴霞"));
System.out.println(str1.replaceAll("AB", "你好"));
char[] c = {'w','c'};
//valueOf
System.out.println(str.valueOf("qqq"));
System.out.println(str.copyValueOf(c));//new String(data);
//intern()方法
/**
When the intern method is invoked, if the pool already contains a
* string equal to this {@code String} object as determined by
* the {@link #equals(Object)} method, then the string from the pool is
* returned. Otherwise, this {@code String} object is added to the
* pool and a reference to this {@code String} object is returned.*/
String s = new String("intern");
System.out.println(s.intern());//重要,当该方法被调用时,如果对象池包含这个字符串,则返回
//对象池的实例,否则添加字符串到对象池并返回该字符串的引用
String s2 = new String("java1");
String s3 = new String("吴霞");
String s4 = "吴霞";
System.out.println("java1" == s2);//false
System.out.println("java1" == s2.intern());//true 思考:为什么?
System.out.println(s3 == s3.intern());//false 思考:为什么? s3是堆上的引用,s3.intern()是从常量池返回的
System.out.println(s3.intern() == s3);//false 思考:为什么?
System.out.println(s4 == s3.intern());//true 思考:为什么?
//String 对 "+"的重载 ,"+"是java 唯一一个重载运算符
//反编译后:
String a = "abc";
String a1 =a + "def";
System.out.println(a1);
int i = 5;
String i1 = "" + i;//相当于 String i1 =(new StringBuilder()).append(i).toString();
String i2 = String.valueOf(i);//调的是 Integer.toString(i); toString(i) 是new 的一个新对象
String i3 = Integer.toString(i);
System.out.println( i2 == i1);//false
System.out.println( i2 == i3);//false