【字符串String类大集合】构造创建_常量池情况_获取方法_截取方法_转换方法_String和基本数据类型互转方法

目录

字符串

在java.lang包下,所以不用导包。
程序中所有的双引号字符串,都是String类的对象(就算没有new也是)

字符串的特点:

1.内容永不可变

2.因为字符串内容不可变,所以可以共享

3.字符串效果上相当于是char[]字符数组,但是底层原理是byte[]字节数组

字符串的常用3+1种构造方法

1public String();创建一个空白字符串, 不含有任何内容

2public String(char[] array);根据字符数组的内容,来创建对应的字符串

3public String(byte[] array);根据字节数组的内筒,来创建对应的字符串

1种直接创建
String str = "Hello";注意:直接写上双引号,就是字符串对象。只要是字符串一定是对象

注意

字符串的比较方法

public boolean equalsIgnoreCase(String str);//忽略大小写进行内容比较

什么情况字符串内容相同就是同一个对象

当字符串在常量池中时,内容相同就是同一个对象

常量池问题讨论

字面量:即''或""括起的部分字符或字符串。例如'a'、'b' 或 '\n'为字符字面量。"Hello,World"为字符串字面量,一旦创建不可更改

1)字符串在常量池的2种情况

  • 字符串字面量(即双直接用引号创建的字符串),就在字符串常量池中。
    即直接创建的字符串在常量池,若内容相同即为共享一个对象,即""通过双引号直接创建的字符串都在常量池 ,内容相同的情况其实是使用的常量池中的同一个对象,所以比较结果为true
    当使用双引号直接定义字符串时(如 String s = "abc";),JVM 会先检查常量池:
    ①若常量池中已存在 "abc",则直接将引用指向该对象;
    ②若不存在,则在常量池中创建 "abc" 并指向它。
    ③这种情况下,字符串必然存在于常量池中。
  • 如果有截取或拼接的操作
    核心判断依据是操作是否在编译期可确定,还是运行期动态生成:
    只有参与拼接的字符串全为 字符串字面量并使用+拼接 后的字符串才在常量池
    若字符串是通过编译期可确定的常量表达式生成的(如字面量拼接),其结果会被编译器直接计算并放入常量池。
    编译期可确定的使用+拼接(常量表达式):结果在常量池。
    注意:只有当拼接的所有部分都是字面量或 final 变量时,结果才会在编译期合并并放入常量池。 例如:
java 复制代码
运行
String s1 = "a" + "b" + "c"; // 编译期直接合并为 "abc",存在于常量池
String s1 = "a";//字符串字面量,直接赋值创建的所以在常量池
String s2 = "b";//同上
String s3 = "a" + s2; // 编译期无法确定(s2 是变量),结果在堆中
String s4 = "a" + "b"; // 编译期确定为 "ab",在常量池
String s5 = "a".concat("b");// 编译期确定为 "ab",在常量池, ●注意!只是内容恰巧相同而非一个对象

concat后在常量池只有一种特殊情况:concat() 的操作结果是编译期可确定的常量表达式,且结果已存在于常量池。也只是内容相同,而非同一个对象

唯一的例外是:如果 concat() 的结果与常量池中的某个字面量完全相同,且该字面量在拼接前已存在于常量池(例如 ("a".concat("b")) 与常量池中的 "ab" 相同),此时两者的值相等,但 concat() 返回的对象本身仍在堆中,只是与常量池中的对象内容一致。
总结:concat() 始终是运行期操作,结果默认在堆中;只有编译期的 + 运算符拼接常量时,结果才会直接进入常量池。 其他操作字符串的方法同理

  • 对于其他的操作方法,都不会在常量池
    例如:new String("a") + new String("b") 的结果是堆中的新对象,需调用 intern() 才会进入常量池。(暂不提)
    substring 方法的结果默认在堆中 ,无论原始字符串是否在常量池。
    replace、replaceAll 等替换操作的结果默认在堆中,即使原始字符串在常量池

2) 字符串不在常量池的情况

构造方法创建的字符串都不在常量池,存在堆中,内容相同也不是同一个对象

哪怕构造器使用同一个数组,创建的内容也完全相同,也是不同的对象

除非是改引用名,本质是同一个对象,即多个引用名指向同一个对象

例如:
char[] charArray = {'a', 'b', 'c'};
String str3 = new String(charArray);
String str4 = str3; 这种情况,给这个对象加了一个引用名
System.out.println(str3 == str4);就是true。相当于同一个对象有两个引用名而已

哪怕用同样的数组构造字符串,只要用来构造方法就是独立的两个对象,如下
String str5 = new String(charArray);
System.out.println(str3 == str4);//true。
System.out.println(str3 == str5);//false

如何判断字符串是否是同一个对象(是否在常量池)

equals和==

== 比较

① 对于基本数据类型比较 内容

② 对于引用类,只有是同一个对象才是true(比较的是对象的内存地址)
equals
只能比较引用对象

① 对于普通类对象,只有同为同一个对象才是true

② 但对于File,String,Data和包装类,是比较内容(因为他们自己重写了tostring方法)

java 复制代码
public class Demo2ConstantPools {
    public static void main(String[] args) {
        String str1 = "abc";
        String str2 = "abc";
        
        char[] charArray = {'a', 'b', 'c'};
        String str3 = new String(charArray);

        byte[] byteArray = { 'a', 'b', 'c'};
        String str4 = new String(byteArray);
        String str5 = new String(byteArray);

        System.out.println(str1 == str2);//true 验证,字面量在常量池是同一个对象
        System.out.println(str2 == str3);//false
        System.out.println(str3 == str4);//false
        System.out.println(str4 == str5);//false 同一个数组做参数,但只要是构造器创建的就不在常量池,在堆,↑str3,4,5都是是独立的两个对象,哪怕内容相同
        
        System.out.println(str1.equals(str2));//true
        System.out.println(str2.equals(str3));//true
        System.out.println(str3.equals(str4));//true
        System.out.println(str4.equals(str5));//true ↑因为内容相同
        
        System.out.println(str1.equalsIgnoreCase("ABC"));//true
    
    }
}

字符串的常用方法

4个获取;长度;拼接;获取索引位置字符;获取字符串首次出现的索引

统一为 String str ; str.方法名来调用
public int length(); 获取字符个数,即字符串长度
public String concat(String str); 将当前字符串和参数拼接返回
public char charAt(int index); 获取指定索引位置的单个字符(第一个字符的索引为0,从0开始)
public int indexOf(String str); 查出参数字符串在本字符串中首次出现的索引位置,没有就return -1

注意:concat方法只会把拼接的结果返回,并不改变调用方法的字符串。除非原字符串接收他的返回值

2种截取方法(重载);左闭右尾;左闭右开

public String substring(int index);截取从参数位置一直到字符串末尾。返回新字符串
public String substring(int begin, int end);截取从begin开始一直到end结束中间的字符串。(按照索引从0开始对应 每一个字符,截取为 [begin,end)左闭右开)

字符串的3种转换相关方法;转char[];转byte[];批量替换指定字符串

public char[] toCharArray();将当前字符串拆分为字符数组作为返回值
public byte[] getBytes();获得当前字符串底层的字节数组
public String replace(CharSequence oldString, CharSequence newString); 将所有出现的老字符替换成为新的字符串,返回替换后的新字符串(CharSequence简单理解为可以接收String类型)

字符串的1种分割方法;删掉给定字符串并分割

public String[] split(String regex);按照参数的规则将字符串切分成为若干部分

特殊情况: 无法根据.划分做参数,split方法的参数其实是一个正则表达式,如果按照英文句"."必须写"\."
注意: . 、 $、 | 和 * 等转义字符,必须得加 \。

split() 方法根据匹配给定的正则表达式来拆分字符串。

★以上所有常用方法使用

java 复制代码
public class Demo3StringMethod {
    public static void main(String[] args) {
        //字符串的4个获取方法
        String str1 = "Hi~Barbie";
        System.out.println(str1.length());//9
        System.out.println(str1.concat("Hi~Ken"));//Hi~BarbieHi~Ken
        System.out.println("索引3的字符" + str1.charAt(3));//B
        str1 = str1.concat("bie~hello java $ rusty lake is fate 1 larua is blossom");
        System.out.println("str1 : " + str1);//Hi~BarbieHi~Kenbie~hello java $ rusty lake is fate 1 larua is blossom
        System.out.println("第一次出现bie的索引位置:" + str1.indexOf("bie"));//6
       
        //字符串的截取方法
        System.out.println("从4截取" + str1.substring(12));//~Kenbie~hello java $ rusty lake is fate 1 larua is blossom
        System.out.println("从[7,13)截取" + str1.substring(17,27));//e~hello ja
        
        //字符串的转换相关方法
        char[] ch = str1.toCharArray();
        System.out.println("char数组:" + ch);
        System.out.println(Arrays.toString(ch));
        byte[] by = str1.getBytes();
        System.out.println("by数组:" + by + Arrays.toString(by));
        for (int i = 0; i < by.length; i++) {
            System.out.print(by[i] + ",");
        }
        System.out.println();
        String str2 = "Hoow doo yoou doo?";
        System.out.println("str2" + str2);
        System.out.println(str2.replace("oo", "*"));

        //字符串的分割方法
        String[] str3 = str1.split("a");
        System.out.println("根据a划分str1:"+ str1);
        for (int i = 0; i < str3.length; i++) {
            System.out.println(str3[i]);
        }
        
 		String str3 = "ewr.e..wfs...as.a.d";
        String[] atr = str3.split("\\.");
        printArray(atr);

        String str4 = "ewr\ne.\nwfs.n.as.d";
        String[] atr2 = str4.split("\\n");
        printArray(atr2);
        
    }
}

❤参与拼接和截取,替换后String的常量池情况

总结: +拼接,并且拼接涉及的所有字符串全为字面量形式。只有这一种操作方式后的字符串在常量池。其他都不在

java 复制代码
	private static void demo02(){
        String s1 = "Barbie";
        String s2 = "Barbie";
        System.out.println(s1 == s2);//true只有这种创建方式字符串在常量池
        //拼接: + concat
        //截取:substring,替换replace,replaceAll
        //❤唯1操作后还在常量池的❤
        String s3 = "Ba"+"rbie";
        System.out.println(s2+"=="+s3 +":" + (s2 == s3));//true
//        String s3 = "ab1c" + "es";
//        String s4 = "ab1c".concat("es");//除了所有操作值都是字面量以外,操作结果已经存在在常量池
//        System.out.println(s3 + "==" + s4 + ":" + (s3 == s4));//false,
        /* s4的操作结果"ab1ces"事先并不在常量池,s3虽然在常量池,但编译期还没有操作完成
        * 就算在==也是false,因为最多内容相同,不可能是同一个对象。concat操作后的值始终在堆*/

        String s4 = "!@#4".concat("1234");//结果事先并不存在,也不在常量池。
        String s44 = "!@" + "#41234";
        System.out.println(s4 + "==" + s44 + ":" + (s4 == s44));//false
        System.out.println(s4 + ".equals" + s44 + ":" + (s4.equals(s44)));//true

        //其他方法 ● substring,replace返回的String都是默认在堆中
        String s5 = "32145Barbie".substring(5);
        String s6 = "231Barbie31".substring(3,9);
        System.out.println(s5 + " == " + s6 + ":" + (s5 == s6));//false
        System.out.println(s5 + ".equals(" + s6 + ":" + (s5.equals(s6)));//true

        String s7 = "123123".replace("12", "Barbie");
        String s8 = "Barbie3Barbie3";
        System.out.println(s7+"=="+s8+ ":" + (s7 == s8));//false
        System.out.println(s7+".equals("+s8+ ":" + (s7.equals(s8)));//true

        String s9 = "123123".replaceAll("12", "Barbie");
        String s10 = "Barbie3Barbie3";
        System.out.println(s7+"=="+s8+ ":" + (s9 == s10));//false
        System.out.println(s7+".equals("+s8+ ":" + (s9.equals(s10)));//true

    }

❤String与基本数据和数组的互相转换

基本数据类型(4类8种)转String

  1. 变量+ "" -->原理:输出时,+字符串之后都默认为字符串,并且拼接

  2. 包装类名.toString(该包装类对应的基本数据类型); 如Integer.toString(i),Double.toString(d)

  3. String.valueOf(基本数据类型); 把基本数据类型转为String类型

java 复制代码
		String bs1 = b +"";
        String ss1 = s + "";
        String is2 = Integer.toString(i);
        String ls2 = Long.toString(l);
        String ds3 = String.valueOf(d);
        String fs3 = String.valueOf(f);

String转基本数据类型

  1. int num = Integer.parseInt(str);//直接解析为int类型的变量
    char:无直接的 parseChar 方法,需通过以下方式:

    若字符串长度为 1,取其首个字符:char c = str.charAt(0);

    若字符串是 Unicode 编码(如 "\u0061"),可先解析为 int 再强转:char c = (char) Integer.parseInt("0061", 16);

  2. int num = Integer.valueOf(str).intValue();//用String做参数装箱后拆箱

    //包装类.valueOf(str)装箱,后intValue()拆箱

    Integer numInt = Integer.valueOf(str);//是包装类

  3. int num = new Integer(str).intValue();//装箱后拆箱

    在这里插入代码片

数组转String

  1. new String([]) 打印字符串;仅支持char[]和byte[]数组
  2. Arrays.toString([]) ;有格式[元素1,元素2,......]
    3.返回参数的String形式String.valueOf(数组名); 仅支持变量和char数组
    Java可用打印数组方法5中+常用变量转字符串方法

易记

类名.toString(基本数据)的类一般为包装类
作用:把基本数据转为String,包装类名和基本数据类型对应
类名.valueOf(参数) 把参数包装到指定类名的类型
作用:装箱,参数可以是基本数据类型和String类型。
类名可以是String和8种包装类,可以把基本类型转String,也可以把String转包装类

相关推荐
lkbhua莱克瓦242 小时前
Java基础——集合进阶5
java·开发语言·集合·泛型
WZTTMoon2 小时前
Spring 配置解析与 @Value 注入核心流程详解
java·spring boot·spring
程序定小飞3 小时前
基于springboot的健身房管理系统开发与设计
java·spring boot·后端
wxin_VXbishe3 小时前
springboot在线课堂教学辅助系统-计算机毕业设计源码07741
java·c++·spring boot·python·spring·django·php
信仰_2739932433 小时前
RedisCluster客户端路由智能缓存
java·spring·缓存
兰雪簪轩3 小时前
仓颉语言内存布局优化技巧:从字节对齐到缓存友好的深度实践
java·spring·缓存
CaracalTiger3 小时前
本地部署 Stable Diffusion3.5!cpolar让远程访问很简单!
java·linux·运维·开发语言·python·微信·stable diffusion
okjohn4 小时前
《架构师修炼之路》——②对架构的基本认识
java·架构·系统架构·软件工程·团队开发
落笔映浮华丶4 小时前
蓝桥杯零基础到获奖-第4章 C++ 变量和常量
java·c++·蓝桥杯