目录
前言:在c中我们如果运用到了字符串就会用到数组或者函数等等,但在Java中,有自己的String类可以调用
因此String是引用类型!
一. 字符串三种常见的构造方法
1.直接赋值
String str1 = "Hello"
2.new一个对象
String str2 = new String("abc")
3.通过字符串转移数组
char[] arr= {'a','b','c'};
String str3 = new String(arr);
既然我们知道String是一个类 那么内部有什么代码呢?
其中我们可以看到 有俩个成员
我们就可以大胆猜测是不是String引用的对象就存储在这俩变量中?
比如以下代码:
public static void main(String[] args) {
String str1 = new String("abc");
String str2 = new String("abc");
}
我们可以通过画图来理解这几行代码
体现到了面向对象的思想
二. 字符串的比较
我们要记住的是String是一个引用类型,不能直接用等号比较,如果使用==比较的话,就是在比较地址!!!
如果比较的是字符串的内容:使用equals方法!!
equals使用字典顺序 返回的是boolean类型
以上代码会输出什么呢?
答案是:
true false
再来看
会打印什么呢?
这是为什么呢?
这就涉及到了字符串常量池的内容,我们先不着急学习,在后面的内容会详细讲解!
2.2 字符串的大小关系
使用compareTo方法
我们通过查询其源码了解到
其返回类型是int 是相差的大小
String 类对compareTo重写过,所以我们才可以调用
三.字符串查找
3.1 charAt:返回index位置上字符,如果index为负数或者越界,抛出
IndexOutOfBoundsException异常
返回的处于index位置上的字符
index的范围是【0,s.length()-1】
例如:
打印结果:
3.2 indexOf:从头开始找,遇到第一个结束 返回目标的位置
public static void main(String[] args) {
String str = new String("abcdef");
System.out.println(str.indexOf('a'));
}
打印结果是:0 就是在str对象中第一个也就是第0位找到目标 a
但是indexOf也有很多分支:
public static void main(String[] args) {
String str = new String("abcdef");
System.out.println(str.indexOf('a'));
String str2 = new String("CIFTIS ends, sees large number of deals, agreements, product launches");
System.out.println(str2.indexOf("number"));
String str3 = new String("ababcab");
System.out.println(str3.lastIndexOf("abc",3));
}
注意这里的最后一个lastIndeOf虽然是从第三位开始从后往前找abc,但还可以读取到,可以将abc看成一个整体!
四.转化
4.1 字符串与数值
public static void main(String[] args) {
int i = 32;
String str = String.valueOf(i);
System.out.println(str);
String str2 = String.valueOf(true); //boolean类型也可以转换!
System.out.println(str2);
String str3 = String.valueOf(new Student("小明",19)); //可以转换类,但类内需要有重写toString方法!!
System.out.println(str3);
}
我们可以看到valueOf方法
4.2 字符串转数字
public static void main(String[] args) {
int val1 = Integer.parseInt("123"); //Integer是包装类型
System.out.println(val1+1);
}
4.3 大小写转换
toUpperCase 小写转大写
toLowerCase 大写转小写
4.4 字符串转数组
tocahrArray:字符串转换成数组
public static void main(String[] args) {
String str = "abc";
char[] chars = str.toCharArray();
System.out.println(Arrays.toString(chars));
}
4.5 格式化
public static void main(String[] args) {
String ret3 = String.format("%d %d %d",2021,12,12);
System.out.println(ret3);
}
五.字符串替换
5.1 replace
public static void main(String[] args) {
String str = "aaaabcd";
String ret = str.replace("a","e");
System.out.println(ret);
}
源码:
这里有个CharSequence 的接口
六. 拆分字符串
split,用法具体如下:
通过以上方法,我们可以观察到如果改变原String,就必须用一个新的String类来接收!
具体原因后面会讲到
如果想要多个分割符,用 | 来隔开!
要知道的是对于 . \ 等特殊字符需要 \\ 来转义!
例如 \\ : 需要 \\\\ 来实现!!
七.截取字符串
substring:
截取,如果是俩个参数 ,那么区间是前闭后开!
八.字符串常量池
常量池的概念:
在JDK1.7之前运行时常量池逻辑包含字符串常量池存放在方法区, 此时hotspot虚拟机对方法区的实现为永久代
在JDK1.7 字符串常量池被从方法区拿到了堆中, 这里没有提到运行时常量池,也就是说字符串常量池被单独拿到堆,运行时常量池剩下的东西还在方法区, 也就是hotspot中的永久代
在JDK1.8 hotspot移除了永久代用元空间(Metaspace)取而代之, 这时候字符串常量池还在堆, 运行时常量池还在方法区, 只不过方法区的实现从永久代变成了元空间(Metaspace)
————————————————
版权声明:本文为CSDN博主「new hilbert()」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Prior_SX/article/details/123463430
那么我们应如何具体感受这个呢? 请看以下代码
打印结果是:
那么我们通过调试来观察一下各个str具体指向的对象!
可以看到 各个str中的value指向的对象 都是
那就证明其实都是指向一个东西,甚至可以说是地址是一样的,为什么会出现false的情况呢?
这里就涉及到了常量池的概念
我们通过模拟其原理画一个草图,为了了解其内部(有纰漏,是为了更容易的理解)
所以 str1 == str2
str3 != str4
也可以通过画图来理解:
但如果加上个这一行代码
str1.intern();
就是将str1指向的对象存入常量池中
要注意一点的是:字符串不可变! 究其原因,网络上大都说是String被final修饰的,其实是错误的!final修饰类只是不能被继承!!! 而真正的原因是:
value被final修饰!指向不能改变,而且其被private修饰 所以无法调用value,来改变String
但是final仅是代表引用类型指向不能改变,但内容可以改变!!
九.StringBuilder和StringBuffer
这俩个只是类! 但也能表示字符串!
public static void main(String[] args) {
StringBuilder stringBuilder = new StringBuilder("Hello");
System.out.println(stringBuilder); //证明这里 重写了toString方法!
//String --> StringBuilder
String s = "Hello";
StringBuilder stringBuilder1 = new StringBuilder(s);
System.out.println(stringBuilder1);
//StringBuilder --> String
StringBuilder stringBuilder2 = new StringBuilder("Hello3");
String s2 = stringBuilder2.toString();
System.out.println(s2);
}
String返回的是新对象
StringBuilder返回this
public static void main(String[] args) {
String str = "abcd";
for (int i = 0; i < 100; i++) {
str += i;
}//这里每一次都要new一个对象
StringBuilder stringBuilder = new StringBuilder("hello");
//stringBuilder.append(str);
for (int i = 0; i < 100; i++) {
stringBuilder.append(i);
}
System.out.println(stringBuilder);
}
那么String 和 StringBuilder、StringBuffer的区别
1.String的内容无法修改,而StringBuilder的内容可以修改
2.StringBuffer与StringBuilder大部分功能是相似的
3.StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安全操作