String类☆
“简单”的介绍:
- String是一个对象!!!
- String 对象用于保存字符串,也是一组字符序列。
- 字符串的字符使用的Unicode字符编码,一个字符(不区分字母还是汉字)都占两个字节
- String 有很多的构造器
String()
初始化新创建的 String对象,使其表示空字符序列。
String(byte[] bytes)
通过使用平台的默认字符集解码指定的字节数组来构造新的 String 。
String(byte[] bytes, Charset charset)
构造一个新的String由指定用指定的字节的数组解码charset 。
String(byte[] ascii, int hibyte)
已弃用
此方法无法将字节正确转换为字符。 从JDK 1.1开始,首选的方法是通过String构造函数获取Charset ,字符集名称,或者使用平台的默认字符集。
String(byte[] bytes, int offset, int length)
通过使用平台的默认字符集解码指定的字节子阵列来构造新的 String 。
String(byte[] bytes, int offset, int length, Charset charset)
构造一个新的String通过使用指定的指定字节子阵列解码charset 。
String(byte[] ascii, int hibyte, int offset, int count)
已弃用
此方法无法将字节正确转换为字符。 从JDK 1.1开始,首选的方式是通过String构造函数获取Charset ,字符集名称,或使用平台的默认字符集。
String(byte[] bytes, int offset, int length, String charsetName)
构造一个新的 String通过使用指定的字符集解码指定的字节子阵列。
String(byte[] bytes, String charsetName)
构造一个新的String由指定用指定的字节的数组解码charset 。
String(char[] value)
分配一个新的 String ,以便它表示当前包含在字符数组参数中的字符序列。
String(char[] value, int offset, int count)
分配一个新的 String ,其中包含字符数组参数的子阵列中的字符。
String(int[] codePoints, int offset, int count)
分配一个新的 String ,其中包含 Unicode code point数组参数的子阵列中的 字符 。
String(String original)
初始化新创建的String对象,使其表示与参数相同的字符序列; 换句话说,新创建的字符串是参数字符串的副本。
String(StringBuffer buffer)
分配一个新的字符串,其中包含当前包含在字符串缓冲区参数中的字符序列。
String(StringBuilder builder)
分配一个新的字符串,其中包含当前包含在字符串构建器参数中的字符序列。
5.String类实现了接口Serializable , CharSequence , Comparable < String >
补充:
一个类只有实现了Serializable接口,它的对象才能被序列化/也叫做串行化。
为什么要序列化对象?
序列化是将对象状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它将流转换为对象。这两个过程结合起来,可以轻松地存储和传输数据。
什么是序列化?
把对象转换为字节序列的过程称为对象的序列化
把字节序列恢复为对象的过程称为对象的反序列化
什么情况下需要序列化?
当我们需要把对象的状态信息通过网络进行传输,或者需要将对象的状态信息持久化,以便将来使用时都需要把对象进行序列化
那为什么还要继承Serializable。那是存储对象在存储介质中,以便在下次使用的时候,可以很快捷的重建一个副本。
再补充:
当一个类实现了Comparable 接口就代表String对象可以比较大小。
- String是个final类,不能被继承。
- String是一个char型的数组。
- 上面看到了 他还 final 修饰 char value [ ] ,所以不可修改(地址不可修改)。既value不能指向新的地址,但是单个字符是可以改变的。
public static void main(String[] args) {
final char[] value = {'g','h','r'};
value[0]= 'H';
for (char c : value) {
System.out.println(c);
}
}
提示:
我修改了单个字符的内容没有报错。
当我再新建一个字符数组的话。让la的地址赋值给value就发现编译不了。注意地址修改不了。
两种创建String对象的方式:
方式一:直接赋值 String s = "我是xxx";
方式二: 调用构造器 String s1 = new String("我是xxx");
两种创建String对象的方式的区别
方式一:先从常量池查看是否有"我是xxx"的数据空间,如果有直接指向;如果没有,则重新创建,然后指向。最终 s指向的是常量池的空间地址。
方式二:现在堆中创建空间,里面有value属性,指向了常量池的“我是xxx”的空间。如果常量池里没有,就重新创建。如果有,就直接通过value指向。最终指向的是堆的空间。
注意:
堆的地址和常量池的地址不一样
更多理解:在这个对象创建流程
小结: 方式1: 直接去常量池中找“我是xxx”,没有就创建一个,有就直接指向栈区的s
方式2:我先创建一个对象,里面有一个value属性,属性的地址指向常量池,如果常量池中有“我是xxx”那么value 直接指向“我是xxx”的地址,再把堆中的地址返回给s1。没有的话,也是在常量池中创建一个。后面给上一句一样。
下面创建了几个对象?
String a = "dadadada";
a = "haha";//两个对象。
//编译器会在底层做个优化 等价于 String a = "dadadadahaha"
String a = "dadadada"+ "haha";//一个对象
String a = "dadadada";//创建a对象
String b= "haha";//创建b对象
String c = a+b;
// 1. 先创建一个 StringBuilder sb = new StringBuilder();在堆中的
//2 . 执行 sb.append("dadadada");
//3. 在执行 sb.append("haha");
//4. String c = sb.toString();
//最后就是c指向堆对象(String)value[] ——> 常量池的“dadadadahaha”
一共三个对象。
总结:
String c = "ab"+"cd" ;常量相加,看的是常量池中的。
String c = a+b;变量相加,在堆中。
String常见的方法
说明:
String类是保存字符串常量,每次更新都需要重新开辟空间,这样效率非常的低,因此java设计者,还提供了StringBuilder 和 StringBuffer来增强String的功能,并提高效率。
类型 | 方法名 | 描述 |
---|---|---|
char | charAt(int index) | 返回 char指定索引处的值。 |
int | compareTo(String anotherString) | 按字典顺序比较两个字符串。 |
int | compareToIgnoreCase(String str) | 按字典顺序比较两个字符串,忽略大小写差异。 |
String | concat(String str) | 将指定的字符串连接到该字符串的末尾。 |
boolean | contains(CharSequence s) | 当且仅当此字符串包含指定的char值序列时才返回true。 |
boolean | contentEquals(StringBuffer sb) | 将此字符串与指定的StringBuffer进行 StringBuffer 。 |
boolean | endsWith(String suffix) | 测试此字符串是否以指定的后缀结尾。 |
boolean | equals(Object, anObject) | 将此字符串与指定对象进行比较。 |
boolean | equalsIgnoreCase(String ,anotherString) | 将此 String与其他 String比较,忽略案例注意事项。 |
static String | format(Locale l, String format, Object… args) | 使用指定的区域设置,格式字符串和参数返回格式化的字符串。 |
static String | format(String format, Object… args) | 使用指定的格式字符串和参数返回格式化的字符串。 |
int | indexOf(int ch) | 返回指定字符第一次出现的字符串内的索引。 |
int | indexOf(int ch, int fromIndex) | 返回指定字符第一次出现的字符串内的索引,以指定的索引开始搜索。 |
int | indexOf(String str) | 返回指定子字符串第一次出现的字符串内的索引。 |
int | indexOf(String str, int fromIndex) | 返回指定子串的第一次出现的字符串中的索引,从指定的索引开始。 |
String | intern() | 返回字符串对象的规范表示。 |
boolean | isEmpty() | 返回 true如果,且仅当 length()为 0 。 |
int | lastIndexOf(int ch) | 返回指定字符的最后一次出现的字符串中的索引。 |
int | lastIndexOf(int ch, int fromIndex) | 返回指定字符的最后一次出现的字符串中的索引,从指定的索引开始向后搜索。 |
int | lastIndexOf(String str) | 返回指定子字符串最后一次出现的字符串中的索引。 |
int | lastIndexOf(String str, int fromIndex) | 返回指定子字符串的最后一次出现的字符串中的索引,从指定索引开始向后搜索。 |
int | length() | 返回此字符串的长度。 |
boolean | matches(String regex) | 告诉这个字符串是否匹配给定的 regular expression 。 |
String | replace(char oldChar, char newChar) | 返回从替换所有出现的导致一个字符串 oldChar在此字符串 newChar 。 |
String | replace(CharSequence target, CharSequence replacement) | 将与字面目标序列匹配的字符串的每个子字符串替换为指定的字面替换序列。 |
String | replaceAll(String regex, String replacement) | 用给定的替换替换与给定的 regular expression匹配的此字符串的每个子字符串。 |
String | replaceFirst(String regex, String replacement) | 用给定的替换替换与给定的 regular expression匹配的此字符串的第一个子字符串。 |
String[] | split(String regex) | 将此字符串分割为给定的 regular expression的匹配。 |
String[] | split(String regex, int limit) | 将这个字符串拆分为给定的 regular expression的匹配。 |
boolean | startsWith(String prefix) | 测试此字符串是否以指定的前缀开头。 |
boolean | startsWith(String prefix, int toffset) | 测试在指定索引处开始的此字符串的子字符串是否以指定的前缀开头。 |
String | substring(int beginIndex) | 返回一个字符串,该字符串是此字符串的子字符串。 |
String | substring(int beginIndex, int endIndex) | 返回一个字符串,该字符串是此字符串的子字符串。 |
char[] | toCharArray() | 将此字符串转换为新的字符数组。 |
String | toLowerCase() | 将所有在此字符 String使用默认语言环境的规则,以小写。 |
String | toLowerCase(Locale locale) | 将所有在此字符 String ,以降低使用给定的规则情况下 Locale 。 |
String | toString() | 此对象(已经是字符串!)本身已被返回。 |
String | toUpperCase() | 将所有在此字符 String使用默认语言环境的规则大写。 |
String | toUpperCase(Locale locale) | 将所有在此字符 String使用给定的规则,大写 Locale 。 |
String | trim() | 返回一个字符串,其值为此字符串,并删除任何前导和尾随空格。 |
StringBuffer类
基本介绍:
-
java.lang.StringBuffer 代表可变的字符序列,对字符串的内容进行增删。
-
很多的方法与String一致,但是StringBuffer是可变长度的。
-
可以看出StringBuffer是继承了 AbstractStringBuilder类,还有实现了Serilalizable接口,代表可以序列化。
-
在父类中 有属性char[ ] value ,不是fianl修饰的,则该数组存放在堆中。
-
StringBuffer类是一个fianl类,不能被继承。
-
StringBuffer保存的是字符串变量,里面的值可以修改,每次StringBuffer的更新实际上可以更新内容,不用每次更新地址,效率高。
-
反观String,String保存的是字符串常量,里面的值不能修改(只有在空间不足时扩容。并重新指向更新后的地址),每次String类的更新实际就是修改地址,效率比较低。
StringBuffer的构造
//1. 创建一个 大小 为16的chhr[ ] ,用来存放字符内容。
StringBuffer stringBuffer = new StringBuffer();
//2. 通过构造器来指定大小
StringBuffer stringBuffer1 = new StringBuffer(20);
//3. 通过给一个String类型的字符来创建StringBuffer,大小是字符串的长度+16。
String A = "36";
StringBuffer stringBuffer2 = new StringBuffer(A);
//4.还可以使用append方法
StringBuffer stringBuffer3 = new StringBuffer();
StringBuffer append = stringBuffer3.append(A);
如何将StringBuffer转成String呢?
- 直接调用toString方法。
- 直接new String();
StringBuilder类:
十分类似与StringBuffer。就是一个线程安全,一个线程不安全。StringBuilder的线程不安全。不适合多线程编程。
三者的区别
1、三者在执行速度方面的比较:StringBuilder >StringBuffer > String
String <(StringBuffer,StringBuilder)的原因
String:字符串常量
StringBuffer:字符串变量
StringBuilder:字符串变量
从上面的名字可以看到,String是“字符创常量”,也就是不可改变的对象。
2、StringBuffer/StringBuilder是生产这个商品的流水线,StringBuffer速度慢,但(线程)安全性高,StringBuilder速度快,但(线程)安全性差。
3、 String 类是final,引用内存中的值不可变。引用数据量一大就不效率,StringBuffer 是用于频繁修改的,而且是线程安全,StringBuilder 是线程不安全。如果只是用来声明一个变量的话就用String,如果用于字符串之间的频繁操作的话就用StringBuffer。
4、如果少量的字符串操作采用String,如果单线程下操作大量字符串采用StringBuilder ,如果多线程下操作大量字符串采用StringBuffer 。
5、StringBuffer、StringBuilder和String一样,也用来代表字符串。String类是不可变类,任何对String的改变都会引发新的String对象的生成;StringBuffer则是可变类,任何对它所指代的字符串的改变都不会产生新的对象。
6、StringBuffer和StringBuilder类的区别也是如此,他们的原理和操作基本相同,区别在于StringBufferd支持并发操作,线性安全的,适合多线程中使用。StringBuilder不支持并发操作,线性不安全的,不适合多线程中使用。新引入的StringBuilder类不是线程安全的,但其在单线程中的性能比StringBuffer高。