字符串那些事儿
引子
在上古时代,阿涛还在更新C语言的时候给兄弟们说过,在C语言中只有字符类,没有字符串类型,我们都是使用char *
指针指向字符串,但是时代变了,在Java中String
也是非常重要的知识点。
写字符串
我们之前说的只要是“ ”起来的内容,都是字符串,经过一段时间的学习,单纯这样理解是远远不够的。
char[]arr={'a','a','f'};
String str=new String("dhhiqhdi");
String str1="adad";
String str2=new String(arr);
常用的构建字符串的方法就在上面了。
品String
Java作为面向对象的主流语言,它把String也写成了一个类,我们先来看看String类中的成员变量:
可以看到String类中的成员变量是一个char类型的数组,还有一个int类型的hash。
String str=new String("dhhiqhdi");
String str1="adad";
事实上,不论我们是显示地new一个String对象还是隐式地使用双引号,都会在堆上创建对象的。那么String是引用类型,按照道理我们每一次都会new一个新的对象的话,是不是使用==比较两个String类都会得到false的结果呢?
String str3="adad";
String str1="adad";
System.out.println(str1==str2);
System.out.println(str1==str3);
这就奇怪了,为什么这跟我们的预期不一样呢?
我们把“ ”括起来的内容都会放到常量池中(“ ”括起来的内容也是一个字符串,也会有相应的value数组和hash值),每当我们创建了String对象,我们首先都会到常量池里面找找看,看看之前有没有存储过,如果我们是直接用“ ”进行赋值的,那么不管是多少个字符串引用,最终都会指向常量池中的字符串,但是如果此时我们进行了new String操作,我们会发现,此时堆上悄咪咪地出现了一个String对象,而此时我们在栈上创建的字符串引用就会指向它。那么有兄弟肯定要问了,那我们字符串的具体内容是怎么样实现的呢?之前不是说了吗,常量池中的也都是一个个鲜活的String对象。我们str指向的对象中的value数组也是会指向常量池中的value数组的,这样子就保持了字符串内容的一致性,毕竟都是指向同一个引用啊。
String str3="adad";
String str1=new String("adad");
System.out.println(str1==str2);
System.out.println(str1==str3);
所以我们现在new一个对象来看看,结果立马变了!
String中的一些方法
之前在C语言中,自己敲了一个又一个方法,着实是有点为难人了,现在我们只要了解个大概就可以上手使用了!
equals
当我们想要比较字符串中的内容的时候,就不要再使用==比较了,我们的String重写了Object中的equals方法,此时比较的就会是两个字符串的内容
char charAt(int index)
获取字符串对应位置的字符
int indexOf(int ch)
返回第一次出现ch的位置,没有返回-1。本质上我们的字符也就是一个个ASCII码值,所以直接‘a’,也是可以的。
int lastIndexOf(int ch)
从后往前找,还是返回位置。这里的indexOf方法中有很多重载,【 )区间的啊,返回出现的字符串的第一个字符的位置啊……
转化
String类中有valueOf方法,这个方法有很多重载
String str=String.valueOf(123);
String str=String.valueOf(1.55);
String str=String.valueOf(new int[]{1,2,3});
这个转化是双向的,我们不单单只有String这一个类啊。
int x=Integer.parseInt("111111");
double y=Double.parseDouble("11.55");
大概就是这么一个使用规则。
replaceAll,replaceFirst
(String regex, String replacement)
第一个参数是要换下的内容,第二个参数是换上的内容。
split
要注意的是这个方法是按照字符串来拆分的,所以参数应该是“ ”类型的。
substring
从某个位置获取到某个位置的方法。
字符串不可变
我们之前一直在强调,我们最后的倔强就是修改字符串的指向,没有说的修改字符串内容的这一说的,包括我们在上面说的这么好些方法,实质上都是返回的是new的新的对象。
我们说的字符串不可变,是因为我们存储字符的value数组被封装起来了,而String类中有没有提供对外的接口,所以我们没有办法在String类外边修改String字符串,而我同时我们的数组又是被final修饰的,所以我们没有办法改变一个字符串对象数组的指向,注意了,我们不可修改的是字符串对象的指向而不是字符串引用的指向,String str,我们这里的str不是想指谁就指谁?
StringBuilder&& StringBuffer
由于使用String中的方法的时候我们每一次都要new一个新对象,这就或多或少会造成我们内存的压力,究其根本原因就是因为我们没有办法直接修改一个String对象,那有没有一种办法,可以让我们直接对字符串进行操作呢?有的,我们这里的StringBuilder和StringBufffer就可以直接实现对字符串的操作:
我们可以看到这两种类的方法中return的都是this,需要注意的是StringBuilder和StringBuffer和String类是独立的,我们不可以以为这两者可以直接转化:
之前我们是利用构造方法实现了String向StringBuffer的转化,反之则需要调用toString方法。
需要注意的是StringBuffer每次使用的时候,都会消耗一部分资源用于保证线程安全,这也就导致了他会比StringBuilder慢一丢丢,这三个类都会有一些自己独特的方法,在这里继续讲解方法就显得没有那么有必要,所以大家可以查阅帮助手册来进行学习!
希望我的这边博客对兄弟们能有所帮助!
还是那句话:百年大道,你我共勉!