文章目录
String类
写在前面的话
在之前的操作中可以发现String可以表示一个字符串,Java中所有的字符串(“abc”)都是此类的实例。
但是使用此类的时候也会发现有一点问题:
从String命名风格可以看出String是一个类,但是此类在使用的时候可以不用构造方法而直接赋值,那么这样的操作有哪些特点呢?
String字符串
字符串是由一个数组构成,因为数组确定长度无法改变,所以字符串是不变的,它的值创建后便的法改变。
String str = “abc”;
相当于
String data[ ] = {‘a’,‘b’,‘c’};
共享内存地址
基于字符串不变性原理,如果创建了两个对象都为"abc",则这两个对象共享同一个内存地址。
例如利用"=="号比较两个对象名,由于比较的是地址,所以返回true;
"=="号除了八种基本数据类型比较的是值,其它时候比较的都是地址。
但注意的是:如果通过new创建字符串,就是不同对象。
String text1 = "abc";
String text2 = new String(original"abc");
此时text1和text2虽然内容一样但地址不同。
字符串常量池
所有被创建的字符串都以常量的形式存储在字符串常量池里。
方法区
方法区又称之为永久代,属于堆的一部分。
方法区是被所有线程共享:
- 此区域存储的是:静态变量;常量;类信息(构造方法\接口定义);常量池;
- 所有定义的方法的信息都存在此区域,此区域属于共享区间。
实例变量存在堆内存中,和方法区无关。
堆
堆在逻辑上分为三层:
- 新生代(YoungGen)
- 老年代(OldGen)
- 永久代(PermGen)
这三者明显的区别就是GC访问的频率不同。
1,新生代:
除了一些特殊的,绝大部分新创建的对象都存在这里。
这里GC访问很频繁,但有些对象访问15次后依旧没有回收,则会自动移入老年代。
2,老年代:
老年代中GC访问频率很低。
3,永久代:
不GC。
什么会放进去?
类只加载一次,加载时放入永久代;静态修饰的所有东西;常量;方法;
每一次字符串对象创建,都会作为常量放入永久代。等到下一次创建字符串对象时,就会进入永久代里面找,如果找到一样对的字符串,就会把之前创建一样的字符串地址加载给对象名。
方法区的演变
到了JDK1.8之后,永久代换了名字,称之为元空间(Metaspace)。操作方法有些许不一样,但绝大部分还是一样的。
String的构造方法
我们基本上是使用基本类型的方式构造String,而通过构造方法构造String对象很少用。
下面列举了String的构造方法,如何去new一个String对象:
构造器 | 描述 |
---|---|
String() | 初始化新创建的 String 对象,使其表示空字符序列。 |
String(byte[] bytes) | 通过使用平台的默认字符集解码指定的字节数组构造新的 String |
String(byte[] bytes, int offset, int length) | 通过使用平台的默认字符集解码指定的字节子阵列来构造新的 String 。 |
String(byte[] bytes, int offset, int length, String charsetName) | 通过使用指定的字符集解码指定的字节子 String 构造新的 String 。 |
String(byte[] bytes, int offset, int length, Charset charset) | 通过使用指定的charset解码指定的字节子String 构造新的String 。 |
String(byte[] bytes, String charsetName) | 构造一个新的String 由指定用指定的字节的数组解码charset 。 |
String(byte[] bytes, Charset charset) | 构造一个新的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) | 分配一个新字符串,其中包含当前包含在字符串构建器参数中的字符序列。 |
String类的所有方法
变量和类型 | 方法 | 描述 |
---|---|---|
char | charAt(int index) | 返回指定索引处的 char 值。 |
IntStream | chars() | 返回 int 的流,将此序列中的 char 值零扩展。 |
int | codePointAt(int index) | 返回指定索引处的字符(Unicode代码点)。 |
int | codePointBefore(int index) | 返回指定索引之前的字符(Unicode代码点)。 |
int | codePointCount(int beginIndex, int endIndex) | 返回此 String 的指定文本范围内的Unicode代码点数。 |
IntStream | codePoints() | 返回此序列中的代码点值流。 |
int | compareTo(String anotherString) | 按字典顺序比较两个字符串。 |
int | compareToIgnoreCase(String str) | 按字典顺序比较两个字符串,忽略大小写差异。 |
String | concat(String str) | 将指定的字符串连接到此字符串的末尾。 |
boolean | contains(CharSequence s) | 当且仅当此字符串包含指定的char值序列时,才返回true。 |
boolean | contentEquals(CharSequence cs) | 将此字符串与指定的 CharSequence 。 |
boolean | contentEquals(StringBuffer sb) | 将此字符串与指定的 StringBuffer 。 |
static String | copyValueOf(char[] data) | 相当于 valueOf(char[\]) 。 |
static String | copyValueOf(char[] data, int offset, int count) | 相当于 valueOf(char[\], int, int) 。 |
boolean | endsWith(String suffix) | 测试此字符串是否以指定的后缀结尾。 |
boolean | equals(Object anObject) | 将此字符串与指定的对象进行比较。 |
boolean | equalsIgnoreCase(String anotherString) | 将此 String 与另一个 String 比较,忽略了大小写。 |
static String | format(String format, Object... args) | 使用指定的格式字符串和参数返回格式化字符串。 |
static String | format(Locale l, String format, Object... args) | 使用指定的语言环境,格式字符串和参数返回格式化的字符串。 |
byte[] | getBytes() | 使用平台的默认字符集将此 String 编码为字节序列,将结果存储到新的字节数组中。 |
void | getBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin) | 已过时。 此方法无法将字符正确转换为字节。 |
byte[] | getBytes(String charsetName) | 使用命名的字符集将此 String 编码为字节序列,将结果存储到新的字节数组中。 |
byte[] | getBytes(Charset charset) | 使用给定的charset将此String 编码为字节序列,将结果存储到新的字节数组中。 |
void | getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin) | 将此字符串中的字符复制到目标字符数组中。 |
int | hashCode() | 返回此字符串的哈希码。 |
int | indexOf(int ch) | 返回指定字符第一次出现的字符串中的索引。 |
int | indexOf(int ch, int fromIndex) | 返回指定字符第一次出现的此字符串中的索引,从指定索引处开始搜索。 |
int | indexOf(String str) | 返回指定子字符串第一次出现的字符串中的索引。 |
int | indexOf(String str, int fromIndex) | 从指定的索引处开始,返回指定子字符串第一次出现的字符串中的索引。 |
String | intern() | 返回字符串对象的规范表示。 |
boolean | isBlank() | 如果字符串为空或仅包含 white space 代码点,则返回 true ,否则 false 。 |
boolean | isEmpty() | 返回 true ,当且仅当, length() 是 0 。 |
static String | join(CharSequence delimiter, CharSequence... elements) | 返回由 CharSequence elements 的副本组成的新String,该副本与指定的 delimiter 的副本连接在一起。 |
static String | join(CharSequence delimiter, Iterable<? extends CharSequence> elements) | 返回由 String 的副本组成的新 String ,其中 CharSequence elements 指定的 delimiter 的副本。 |
int | lastIndexOf(int ch) | 返回指定字符最后一次出现的字符串中的索引。 |
int | lastIndexOf(int ch, int fromIndex) | 返回指定字符最后一次出现的字符串中的索引,从指定的索引开始向后搜索。 |
int | lastIndexOf(String str) | 返回指定子字符串最后一次出现的字符串中的索引。 |
int | lastIndexOf(String str, int fromIndex) | 返回指定子字符串最后一次出现的字符串中的索引,从指定索引开始向后搜索。 |
int | length() | 返回此字符串的长度。 |
Stream<String> | lines() | 返回从此字符串中提取的行的流,由行终止符分隔。 |
boolean | matches(String regex) | 判断此字符串是否与给定的 regular expression匹配。 |
int | offsetByCodePoints(int index, int codePointOffset) | 返回此 String 中的索引,该索引从给定的 index 偏移 codePointOffset 代码点。 |
boolean | regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) | 测试两个字符串区域是否相等。 |
boolean | regionMatches(int toffset, String other, int ooffset, int len) | 测试两个字符串区域是否相等。 |
String | repeat(int count) | 返回一个字符串,其值为此字符串的串联重复 count 次。 |
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 | strip() | 返回一个字符串,其值为此字符串,并删除了所有前导和尾随 white space 。 |
String | stripLeading() | 返回一个字符串,其值为此字符串,并删除了所有前导 white space 。 |
String | stripTrailing() | 返回一个字符串,其值为此字符串,并删除所有尾随 white space 。 |
CharSequence | subSequence(int beginIndex, int endIndex) | 返回作为此序列的子序列的字符序列。 |
String | substring(int beginIndex) | 返回一个字符串,该字符串是此字符串的子字符串。 |
String | substring(int beginIndex, int endIndex) | 返回一个字符串,该字符串是此字符串的子字符串。 |
char[] | toCharArray() | 将此字符串转换为新的字符数组。 |
String | toLowerCase() | 使用默认语言环境的规则将此 String 所有字符转换为小写。 |
String | toLowerCase(Locale locale) | 使用给定 Locale 的规则将此 String 所有字符转换为 Locale 。 |
String | toString() | 这个对象(已经是一个字符串!) |
String | toUpperCase() | 使用默认语言环境的规则将此 String 所有字符转换为大写。 |
String | toUpperCase(Locale locale) | 使用给定 Locale 的规则将此 String 所有字符转换为大写。 |
String | trim() | 返回一个字符串,其值为此字符串,删除了所有前导和尾随空格,其中space被定义为其代码点小于或等于 'U+0020' (空格字符)的任何字符。 |
static String | valueOf(boolean b) | 返回 boolean 参数的字符串表示形式。 |
static String | valueOf(char c) | 返回 char 参数的字符串表示形式。 |
static String | valueOf(char[] data) | 返回 char 数组参数的字符串表示形式。 |
static String | valueOf(char[] data, int offset, int count) | 返回 char 数组参数的特定子数组的字符串表示形式。 |
static String | valueOf(double d) | 返回 double 参数的字符串表示形式。 |
static String | valueOf(float f) | 返回 float 参数的字符串表示形式。 |
static String | valueOf(int i) | 返回 int 参数的字符串表示形式。 |
static String | valueOf(long l) | 返回 long 参数的字符串表示形式。 |
static String | valueOf(Object obj) | 返回 Object 参数的字符串表示形式。 |
String字符串的拼接
String a = "123";
String b = "456";
String c = "789";
a = a+b+c;
System.out.print(a);
拼接逻辑如下:
a = a+b+c:首先从a和b中调用内容,然后开辟出新空间把拼接内容存储;接着调用c和刚刚开辟新空间里的内容,再开辟新空间把新的拼接内容存储。然后a指向改新开辟存储了a+b+c的地址。
在这里就出现了一个问题,存储"123"和"123456"的地址没有对象名引用,变成了内存垃圾。而且GC不回收。
拼接的另一种更好方法
StringBuffer和StringBuilder类,两者都包含拼接字符串的方法。
拼接后产生的垃圾会被GC回收,不会占用内存。
步骤
1,首先通过无参构造方法new一个对象;
StringBuffer() | 构造一个字符串缓冲区,其中没有字符,初始容量为16个字符。 |
---|
本质是创建一个数组,然后等往这个数组里面传内容,当超过数组容量,数组就会自动扩容,扩容后产生的垃圾会被GC回收。
2,然后通过append方法不断传入要拼接的字符串:
变量和类型 | 方法 | 描述 |
---|---|---|
StringBuffer | append(boolean b) | 将 boolean 参数的字符串表示形式追加到序列中。 |
StringBuffer | append(char c) | 将 char 参数的字符串表示形式追加到此序列。 |
StringBuffer | append(char[] str) | 将 char 数组参数的字符串表示形式追加到此序列。 |
StringBuffer | append(char[] str, int offset, int len) | 将 char 数组参数的子数组的字符串表示形式追加到此序列。 |
StringBuffer | append(double d) | 将 double 参数的字符串表示形式追加到此序列。 |
StringBuffer | append(float f) | 将 float 参数的字符串表示形式追加到此序列。 |
StringBuffer | append(int i) | 将 int 参数的字符串表示形式追加到此序列。 |
StringBuffer | append(long lng) | 将 long 参数的字符串表示形式追加到此序列。 |
StringBuffer | append(CharSequence s) | 将指定的 CharSequence 追加到此序列。 |
StringBuffer | append(CharSequence s, int start, int end) | 将指定的 CharSequence 序列附加到此序列。 |
StringBuffer | append(Object obj) | 追加 Object 参数的字符串表示形式。 |
StringBuffer | append(String str) | 将指定的字符串追加到此字符序列。 |
StringBuffer | append(StringBuffer sb) | 将指定的 StringBuffer 追加到此序列。 |
3,然后使用subString方法返回成字符串类型;(StringBuilder是toString)
String | substring(int start) | 返回一个新的 String ,其中包含此字符序列中当前包含的字符的子序列。 |
---|---|---|
String | substring(int start, int end) | 返回一个新的 String ,其中包含当前包含在此序列中的字符的子序列。 |
StringBuffer sb = new StringBuffer();
sb.append("1");
sb.append("2");
sb.append("3");
String text = sb.subString();
System.out.print(text);
StringBuilder和上面使用方法一模一样,就不赘述。