String类
String类的理解和创建对象
- String 对象用于保存字符串,也就是一组字符序列
- 字符串常量是用双引号括起来的字符序列,例如:“你好”、“12.97”、"boy"等
- 字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节
- String类较常用构造方法(其他看手册)
String s1 = new String();
String s2 = new String(String original);
String s3 = new String(char[] a);
String s4 = new String(char[] a,int startIndex,int count)
package com.tao.string_;
/**
* Create By 刘鸿涛
* 2022/1/1 18:31
*/
public class String01 {
public static void main(String[] args) {
//1.String 对象用于保存字符串,也就是一组字符序列
//2."jack" 字符串常量,双引号括起来的字符串
//3.字符串的字符使用Unicode字符编码,一个字符(不区分字母还是汉字)占两个字节
//4.String 类有很多构造器,构造器的重载
// 常用的有
//String s1 = new String();
//String s2 = new String(String original);
//String s3 = new String(char[] a);
//String s4 = new String(char[] a,int startIndex,int count);
//String s5 = new String(byte[] b);
//5.String 类实现了接口 Serializable 【String 可以串行化:可以在网络传输】
// 接口 Comparable 【String 对象可以比较大小】
//6.String 是final 类,不能被其他类继承
//7.String 有属性 private final char value[];用于存放字符串内容
//8.一定要注意:value 是一个final类型,不可以修改【即value不能指向新的地址
// ,但是单个字符内容是可以变化】
String name = "jack";
name = "tom";
final char[] value = {'a','b','c'};
char[] v2 = {'t','o','m'};
value[0] = 'H';
// value = v2; 不可以修改 value地址
}
}
创建String对象的两种方式
方式一:直接赋值
String s = “hspedu”;
方式二:调用构造器
String s = new String(“hspedu”);
- 方式一:先从常量池查看是否有“hsp“数据空间,如果有,直接指向;如果没有则重新创建,然后指向,s最终指向的是常量池的空间地址
- 方式二:现在堆中创建空间,里面维护了value属性,指向常量池的hsp空间。如果常量池没有“hsp”,重新创建,如果有,直接通过value指向。最终指向的是堆中的空间地址。
- 画出两种方式的内存分布图
案例分析
String a = "abc";
String b = "abc";
System.out.println(a.equals(b)); //字符串,比较value[]数组 T
System.out.println(a == b); //地址 T 因为常量池在String a 后被创建了对象,b也指向这一个地址
intern()
当调用intern方法时,如果池已经包含一个等于此String对象的字符串(用equals(Object)方法确定),则返回池中的字符串。否则,将此String 对象添加到池中,并返回此 String 对象的引用
b.intern()方法最终返回的是常量池的地址(对象)
String a = "taotao"; //a指向 常量池的 “taotao”
String b = new String("taotao"); //b 指向堆中对象
System.out.println(a.equals(b)); //字符串数组相等 T
System.out.println(a == b); //地址不同 F
System.out.println(a == b.intern()); //返回常量池地址 T
System.out.println(b == b.intern()); //b指向堆,b.intern()指向常量池 F
String s1 = "taotao"; //s1指向常量池对象
String s2 = "java"; //s2指向常量池对象
String s4 = "java"; //s4与s2指向同一个常量池对象
String s3 = new String("java"); //s3 指向堆中对象 value指向常量池java
System.out.println(s2 == s3); //地址不同,不相等 F
System.out.println(s2 == s4); //同一个常量池地址 T
System.out.println(s2.equals(s3)); //内容相等 T
System.out.println(s1 == s2); //不是同一个对象 F
对象内存布局分析
Person p1 = new Person(); //创建Person对象p1,开辟空间
p1.name = "taotao"; //p1.name指向常量池,String
Person p2 = new Person(); //创建Person对象p2,开辟空间
p2.name = "taotao"; //p2.name指向常量池,String
System.out.println(p1.name.equals(p2.name)); //内容相等 T
System.out.println(p1.name == p2.name); //指向常量池地址相同 T
System.out.println(p1.name == "taotao"); //指向常量池地址相同 T
String s1 = new String("bcde");
String s2 = new String("bcde");
System.out.println(s1 = s2); //new出来的是两个对象 F