String类 和 常量池
文章目录
1、常量池的位置
jdk 1.7之前常量池是存放在永久代(hotspot虚拟机对方发区的实现)中
jdk 1.7常量池从永久代中移到了堆内存中,属于堆内存的一部分。
Jdk 8 移除了永久代并由元空间(metaspace)代替,存放在本地内存(native space)中。并没有对常量池再做变动。即常量池一直在堆中。
2、String对象的两种创建方式:
String s1 = "123";
String s2 = new String("123");
System.out.println(s1 == s2); // false
这两种创建方式是不同的,第一种是在常量池中拿对象,第二种是在堆中 new 对象 产生了新的内存(只要new 就会产生新的对象)
3、String类型的常量池比较特殊。使用方式主要有两种
-
直接使用双引号声明出来的String对象会直接存储在常量池中。
-
如果不是用双引号声明的String对象,可以使用String提供的intern方法–是一个native方法
作用:-
如果运行时常量池中已经包含一个等于此String对象内容的字符串,则返回常量池中该字符串的引用
-
如果没有,则在常量池中创建与此 String 内容相同的字符串,并返回常量池中创建的字符串的引用
String s1 = new String("计算机"); String s2 = s1.intern(); String s3 = "计算机"; System.out.println(s2);//计算机 System.out.println(s1 == s2);//false, //因为一个是堆内存中的String对象,一个是常量池中的String对象 两块的地址是不一样的 System.out.println(s3 == s2);//true,因为两个都是常量池中的String对象
-
4、 String字符串拼接
String str1 = "str";
String str2 = "ing";
String str3 = "str" + "ing";//常量池中的对象
String str4 = str1 + str2; //在堆上创建的新的对象
String str5 = "string";//常量池中的对象
System.out.println(str3 == str4);//false
System.out.println(str3 == str5);//true
System.out.println(str4 == str5);//false
****
注意:
在程序开发中,尽量避免使用String进行字符拼接,因为会产生大量常量垃圾
因此 使用 StringBulider 和 StringBuffer 类 stringBuffer 是 线程安全的, StringBuild 是线程不安全
具体使用看需求。
题目: String s1 = new String(“abc”);这句话创建了几个对象?答:创建了两个对象。
**解释:**先有字符串"abc"放入常量池,然后 new 了一份字符串"abc"放入Java堆(字符串常量"abc"在编译期就已经确定放入常量池,而 Java 堆上的"abc"是在运行期初始化阶段才确定),然后 Java 栈的 str1 指向Java堆上的"abc"。
5、String类的常用方法
构造方法
构造方法 | 描述 |
---|---|
String(String original) | 初始化新创建的String 对象,使其表示与参数相同的字符序列; 换句话说,新创建的字符串是参数字符串的副本。 |
String(byte[] bytes) | 通过使用平台的默认字符集解码指定的字节数组构造新的 String |
String(byte[] bytes, String charsetName) | 构造一个新的String 由指定用指定的字节的 编码方式 |
String(char[] value) | 分配新的 String ,使其表示当前包含在字符数组参数中的字符序列。 |
方法
- valueOf ——将参数转换成字符串
返回类型 | 方法 | 描述 |
---|---|---|
char | charAt(int index) | 返回指定索引处的 char 值。 |
int | compareTo(String anotherString) | 按字典顺序比较两个字符串。小于就返回负数 |
int | compareToIgnoreCase(String str) | 按字典顺序比较两个字符串,忽略大小写差异。 |
boolean | contains(CharSequence s) | 当且仅当此字符串包含指定的char值序列(子串)时,才返回true。 |
boolean | endsWith(String suffix) | 测试此字符串是否以指定的后缀结尾。 |
boolean | startsWith(String prefix) | 测试此字符串是否以指定的前缀开头 |
byte[] | getBytes() | 使用平台的默认字符集将此 String 转换为byte[] |
byte[] | getBytes(String charsetName) | 使用指定的字符集将此 String 转换为byte[] |
int | indexOf(int ch) | 返回指定字符第一次出现的字符串中的索引。 |
int | indexOf(int ch, int fromIndex) | 返回指定字符第一次出现的此字符串中的索引,从指定索引处开始搜索。 |
int | indexOf(String str) | 返回指定子字符串第一次出现的字符串中的索引。 |
int | indexOf(String str, int fromIndex) | 从指定的索引处开始,返回指定子字符串第一次出现的字符串中的索引。 |
int | lastIndexOf(int ch) | 返回指定字符最后一次出现的字符串中的索引(与indexof一样) |
String | intern() | 返回字符串对象的规范表示 |
int | length() | 返回此字符串的长度。 |
boolean | matches(String regex) | 是否符合该 正则表达式 |
String | replace(char oldChar, char newChar) | 返回从替换所有出现的导致一个字符串 oldChar 在此字符串 newChar 。 |
String | replace(CharSequence target, CharSequence replacement) | 将此字符串中与文字目标序列匹配的每个子字符串替换为指定的文字替换序列。 |
String | replaceFirst(String regex, String replacement) | 将给定替换的给定正则表达式匹配的此字符串的第一个子字符串替换。 |
String[] | split(String regex) | 根据 给定的字符分组 |
String | trim() | 去除字符串的首尾所有空格 |
String | toUpperCase() | 将字符串中的字符全部转为大写字符 |
String | toLowerCase() | 将字符串中的字符全部转为小写字符 |
char[] | toCharArray() | 将此字符串转换为新的字符数组。 |
String | substring(int beginIndex, int endIndex) | 截取字符串(左闭右开) |
参数: ignoreCase : true - 忽略大小写
toffset - 哪个偏移量开始
other : 字符子串
ooffset :子串的偏移量
len : 字串要比较的长度
-
split(String regex, int limit)
-
limit
参数控制应用模式的次数,因此会影响结果数组的长度。- 如果限制为正,则模式将应用最多限制 - 1次,数组的长度不会超过限制 ,并且数组的最后一个条目将包含超出最后一个匹配分隔符的所有输入。
- 如果限制为零,则模式将尽可能多地应用,数组可以具有任何长度,并且将丢弃尾随空字符串。
- 如果限制为负,则模式将尽可能多地应用,并且数组可以具有任何长度。
例如,字符串
"boo:and:foo"
使用以下参数生成以下结果:
-
- 返回一个字符串,该字符串是此字符串的子字符串。 子字符串从指定的
beginIndex
开始,并扩展到索引endIndex - 1
处的字符。 因此子串的长度是endIndex-beginIndex
。