目录
为什么输出String类型的变量不是地址而输出对象却是地址?
String类
String类的Diagram
String类的理解和创建对象
-
String对象用于保存字符串,也就是一组字符序列
-
String是引用类型
-
字符串常量对象是用双引号括起来的字符序列。例如:"你好"、"12.66"、"boy"等
-
字符串的字符使用Unicode字符编码,一个字符(不区分字母还是数字)占两个字节
-
String类常用的构造器(其它看手册):
-
String s1 = new String();
-
String s2 = new String(String original);
-
String s3 = new String(char[] a);
-
String s4 = new String(char[],int startIndex,int count)
-
-
String类实现了Serializable接口,所以String可以串行化(可以在网络上传输)
-
String类实现了Comparable接口,所以String对象可以比较大小
-
String类是final类,不能被其它的类继承
-
String有属性 private final char value[]; 用于存放字符串内容
-
注意:final修饰的是value这个引用变量,所以value引用变量存放的地址不可以修改
-
为什么输出String类型的变量不是地址而输出对象却是地址?
因为所有的类继承了Object类,所以单独输出一个对象的时候,他会调用 Object.toString() 方法,打印出来的就是一串表达地址的字符串,最后调用的是Object类的toString方法。
* @return a string representation of the object. :返回该对象的一个字符串表现形式
String类里重写了Object类的toString()方法,它返回的是String自己,String是什么呢,String其实就是字符数组,它内部封装了一个字符数组,所以打印字符串就是打印字符数组,而不是地址。
* @return the string itself.:返回字符串本身
String对象的两种创建方式
-
方式1:直接赋值 String s = "word";
-
先从常量池查看是否有"word"数据空间,如果有,则直接指向;如果没有则重新创建,然后指向。s指向的是常量池的空间地址。
-
-
方式2:调用构造器 String s = new String("word");
-
先在堆中创建空间,里面维护了value属性,指向常量池的"word"空间。如果常量池没有"word",则重新创建,如果有,则直接通过value指向。s指向的是堆中的空间地址。
-
String对象的特性
-
String是一个final类,代表不可变的字符序列
-
字符串是不可变的。一个字符串对象一旦被分配,其内容是不可变的
1.以下语句创建了几个对象?
String s1 = "hello";
s1 = "abc";
解析:创建了两个对象;String的引用指向可以改变;value的指向其实并没有改变;常量池属于堆中的一部分
2.以下语句创建了几个对象?
String a = "hello"+"abc";
创建了一个对象;编译器会进行优化;等价于 -> String a = "helloabc";
3.以下语句创建了几个对象?
String a = "hello";
String b = "abc";
String c = a+b;
创建了四个对象;执行String c = a+b;语句时,先创建了一个 StringBuilder sb = StringBuilder()对象;然后执行 sb.append("hello");再执行sb.append("abc");接着再执行 String c = sb.toString()。最后其实是 c 指向堆中的对象;对象中的value[] -> 常量池中的"helloabc"
4.以下代码输出什么?
String s1 = "abc";
String s2 = "java";
String s3 = "abcjava";
String s4 = (s1+s2).intern();
System.out.println(s3 = s4);
System.out.println(s3.eaquals(s4));
输出 true 、true;intern()方法返回的是常量池中的地址
重要规则
-
String h = "ab"+"cd"; 字符串常量相加,指向常量池
-
String h= a+b; 变量相加,指向堆中
String类的常用方法
String类的常用方法1
-
equals() :区分大小写,判断内容是否相等
-
equalsIgnoreCase() :忽略大小写,判断内容是否相等
-
length() :获取字符的个数,即字符串的长度
-
contains():判断字符串中是否有子字符串,如果有则返回true,如果没有则返回false
-
indexOf() :获取字符(或字串)在字符串中第一次出现的索引,索引从0开始,如果找不到,返回 -1
-
lastIndexOf() :获取字符(或子串)在字符串中最后一次出现的索引,索引从0开始,如果找不到,返回 -1
-
valueOf():将传入的 基本数据类型 转换成 String 类型
-
subString() :截取指定范围的子串
-
trim() :去前后空格
-
charAt() :获取某索引处的字符,注意不能使用Str[index] 这种方式
String str = "hello";
//str[0] 不对,str不是数组
//str.charAt(0) -> h,正确
String类的常用方法2
-
toUpperCase() :字符串全部转换成大写
-
toLowerCase() :字符串全部转换成小写
-
concat() :拼接字符串
-
replace() :替换字符串中的字符
public final class Demo07 {
public static void main(String[] args) {
String s1 = "宝玉 and 林黛玉";
//"宝玉 and 林黛玉"常量对象并没有被改变,只是s1的指向改变了
s1 = s1.replace("宝玉","jack");
System.out.println(s1);
System.out.println(s1.replace("jack","宝玉"));
System.out.println(s1);
}
}
-
split():分割字符串,返回一个String类型的数组。对于某些特殊字符,如 | \ 等,需要加入 转义符 \ 进行转义;如果分割的条件是空字符串"",则按单个字符进行分割成一个String类型的数组。
-
toCharArray():转换成字符数组
-
compareTo():比较两个字符串的大小,如果前者大,则返回正数;后者大,则返回负数;如果相等,返回0
-
如果字符串长度相同,并且每个字符也相同,就返回0
-
如果长度相同或者不相同,但是在进行比较时,可以区分大小,就返回
if (c1 != c2) {
return c1 - c2 //字符对应的ASCll值进行相减
}
-
如果前面的部分都相同,就返回 str1.length() - str2.length()
-
-
format():格式化字符串。%s、%d、%.2f、%c 称为占位符,这些占位符由后面变量顺序来替换
-
%s 表示后面使用字符串来替换
-
%d 表示后面使用整数来替换
-
%.2f 表示后面使用小数来替换,只会保留小数点后两位,并且会进行四舍五入处理
-
%c 表示后面使用char类型来替换
-
public final class Demo07 {
public static void main(String[] args) {
String name = "join";
int age = 10;
double score = 89.6677;
char gender = '男';
String info = String.format("我的姓名是%s年龄是%d,成绩是%.2f性别是%c.",name,age,score,gender);
System.out.println(info);
}
}