Java--String类方法介绍和部分源码解析

1.内存部署

  1. 1.字符串的初始化三种方案
public static void StringInit() {
    
    
        String str = "hello";
        System.out.println(str);
        String str2 = new String("hello");
        System.out.println(str2);
        char[] ch = {
    
    'h', 'e', 'l', 'l', 'o'};
        String str3 = ch.toString();
        System.out.println(str3);
    }
  1. 2.String字符串比较相等,不可修改的特性

ctrl+鼠标:点击String,我们会发现一个String的构造方法
在这里插入图片描述
ctrl+鼠标再点击value会发现这个value是被final修饰String一个实例成员变量字符数组,隶属于对象
在这里插入图片描述
this.value数组存储的形参中的value值。此时的value存储的时常量池中字符串的地址【为什么是地址:因为当字符串加载的时候,都会加载到常量池中。示例代码中String str = “hello"已经在常量池中加载,因此new String(“hello”)不需要额外消耗资源去加载常量池的"hello”。即使没有第一个的赋值影响,new String也会再次进行常量池加载】
因此我们每次new String(“xxx”)时创建的字符串

public static void StringCompare() {
    
    
        /**
         * JDK1.7开始,字符串常量池 被挪到了 堆 中
         */
        String str1 = "hello";
        String str2 = new String("hello");
        String str3 = "hello";
        System.out.println(str1 == str2);//false:== 比较的是引用
        System.out.println(str1 == str3);//true:常量池中已经有了hello,因此不用继续放"hello"

        String str4 = "hel" + "lo";// 编译时期已经被处理为"hello"
        String str5 = new String("hel" + "lo");
        System.out.println(str1 == str4);//true
        System.out.println(str1 == str5);//false

        final int a = 10;
        int c = a + 30;

        String str6 = str1;
       str6 = "world";//只是改变了str6的指向,并没有达到修改只想内容的效果。因为String的常量不可被修改【传引用不会修改值,对于数组而言拿引用修改值才可以达到指向内容修改的效果】
        str6 = 'w' + str1.substring(1);//一个'h'拼接str1从第二个元素开始到最后一个元素[包含最后一个元素]截止所有字符串。但是依旧没有修改str1的内容

        /*
        null.equals(str): 会报错
        而str.equals(null): 不会报错
        因此建议str.equals(null)来比较。将被比较的的对象放入equals内部,已经确定的对象放在equals外部
         */
        System.out.println(str1.equals(str5));//true: equals比较的是内容而不是引用

        /**
         * intern手动入池,从现象上看的
         * 当前的这个字符串在常量池中是否存在?如果存在,把常量池中的引用赋值给当前的引用类型变量
         */
        String str7 = new String("hel" + "lo").intern();
        System.out.println(str1 == str7);//true

        /*
        如下代码会残生大量临时变量在常量池中
        后续中用StringBuffer或者StringBuilder拼接
         */
        /*String str8 = "hello";
        for (int i = 0; i < 1000; i++) {
            str8 += i;
        }*/
    }

内存布局
在这里插入图片描述

常量在编译时的状态
javac -encoding 编码格式 文件名.java
javap -c 文件名.class
在这里插入图片描述
在这里插入图片描述

3.反射机制
    public static void reflect() throws NoSuchFieldException, IllegalAccessException {
    
    
        // 利用反射--》自省的过程
        String str = "Hello";
        Class cl = String.class;
        Field field = cl.getDeclaredField("value");
        field.setAccessible(true);
        char[] val = (char[]) field.get(str);
        val[0] = 'g';
        System.out.println(str);
    }

在这里插入图片描述

2.常用方法

  1. 1.字符数组转换为字符串
    public static void chararray_To_String() {
    
    
        /*
        字符数组--》字符串
         */
        char[] ch = {
    
    'a', 'b', 'c', 'd', 'e'};
        String str = ch.toString();// 字符数组.toString全部转换
        String str2 = new String(ch);// new String(字符数组)全部转换
        String str3 = new String(ch, 1, 3);// new String(起始位置, 偏移量)部分转换或者全部转换
        System.out.println(str);
        System.out.println(str2);
        System.out.println(str3);
    }

[C@1540e19d
abcde
bcd
  1. 2.字符串–》字符
    public static void String_To_char() {
    
    
        /*
        字符串--》字符
         */
        String str4 = "Hello";
        char ch2 = str4.charAt(0);// 把字符串转换为字符,取字符
    }

ch2: H
Hello
  1. 3.字符串–》字符数组
    public static void String_To_chararray() {
    
    
        /*
        字符串--》字符数组
         */
        String str = "Hello";
        char[] ch = str.toCharArray();
    }
    
[H, e, l, l, o]
  1. 4.字节数组–》字符串
    public static void byte_To_String() {
    
    
        /*
        字节数组--》字符串
         */
        byte[] bytes = {
    
    97, 98, 99, 100};
        String str = bytes.toString();
        String str2 = new String(bytes, 1, 3);
        System.out.println(str);
        System.out.println(str2);
    }
    
[B@1540e19d
bcd
  1. 5.字符串–》字节数组
    public static void String_To_bytearray() {
    
    
        /*
        字符串--》字节数组
        那么何时使用 byte[], 何时使用 char[] 呢?
        byte[] 是把 String 按照一个字节一个字节的方式处理, 这种适合在网络传输, 数据存储这样的场景下使用. 更适合针对二进制数据来操作.
        char[] 是吧 String 按照一个字符一个字符的方式处理, 更适合针对文本数据来操作, 尤其是包含中文的时候.
         */
        String str = "Hello";
//        byte[] bytes = str.getBytes("utf8");
        byte[] bytes2 = str.getBytes();
        System.out.println(Arrays.toString(bytes2));
    }

[72, 101, 108, 108, 111]

带有@Deprecated注解说明已经被弃用

在这里插入图片描述

  1. 6.字符串内容比较
    public static void String_equals() {
    
    
        /*
        字符串内容比较
         */
        String str1 = "hello";
        String str2 = "Hello";
        System.out.println(str1.equals(str2)); // false
        System.out.println(str1.equalsIgnoreCase(str2)); // true
    }

equals源码可知:因为是一个一个内容进行比较在这里插入图片描述

  1. 7.字符串大小比较
    public static void String_compareTo() {
    
    
        /*
        字符串大小比较
         */
        String str1 = "hello";
        String str2 = "Hello";
        System.out.println(str1.compareTo(str2));
    }
32[有一定的规律,ASCII值差]

字符串比较大小函数,是String自带重写compare函数之后的效果。需要注意他的返回值类型是int
在这里插入图片描述

  1. 8.replace 和 replaceAll 几乎没有差别
    public static void String_replace() {
    
    
        /*
        replace 和 replaceAll 几乎没有差别
         */
        String str = "helloworld";
        System.out.println(str.replace("l", "_"));
        System.out.println(str.replaceAll("l", "_"));
        System.out.println(str.replaceFirst("l", "_"));// 替换第一个出现的
    }

he__owor_d
he__owor_d
he_loworld
  1. 9.字符串截取
    public static void String_substring() {
    
    
        /*
        字符串截取
         */
        String str = "helloworld";
        System.out.println(str.substring(5));// 从此位置开始截取到结束位置
        System.out.println(str.substring(0, 5));//[0, 5)
    }
    
world
hello
  1. 10.字符串去空白
    public static void String_trim() {
    
    
        /*
        字符串去空白
         */
        String str = " hello world ";
        System.out.println("[" + str + "]");
        System.out.println("[" + str.trim() + "]");
    }

[ hello world ]
[hello world]
  1. 11.字符串查找
    public static void String_contains() {
    
    
        /*
        字符串查找
         */
        String str = "helloworld";
        System.out.println(str.contains("world")); // true

        System.out.println(str.indexOf("world")); // 5,w开始的索引
        System.out.println(str.indexOf("bit")); // -1,没有查到
        System.out.println(str.indexOf("world", 3));//无论几开始,都是0计算下标
        System.out.println(str.lastIndexOf("world"));
        System.out.println(str.lastIndexOf("world", 90));
    }

true
5
-1
5
5
5

  1. 12.字符串开头或者结尾匹配
    public static void String_with() {
    
    
        /*
        字符串开头或者结尾匹配
         */
        String str = "**@@helloworld!!";
        System.out.println(str.startsWith("**")); // true
        System.out.println(str.startsWith("@@", 2)); // ture
        System.out.println(str.endsWith("!!")); // true
    }

true
true
true
  1. 13.字符串切割
    public static void String_split() {
    
    
        /*
        字符串切割
         */
        String str = "hello world hello bit";
        String[] result = str.split(" "); // 按照空格拆分
        for (String s : result) {
    
    
            System.out.println(s);
        }

        String str2 = "192.168.1.1";
        String[] result2 = str2.split("\\.");
        for (String s : result2) {
    
    
            System.out.println(s);
        }

        // 分割多次
        String str3 = "name=zhangsan&age=18";
        String[] result3 = str3.split("&");
        for (int i = 0; i < result3.length; i++) {
    
    
            String[] temp = result3[i].split("=");
            System.out.println(temp[0] + " = " + temp[1]);
        }
    }

hello
world
hello
bit
192
168
1
1
name = zhangsan
age = 18

下图是字符串切割函数源码。我们需要注意红色圈圈部分特殊字符需要用"\\"进行处理
在这里插入图片描述

说明我们字符串切割的split返回的是一个String[] 字符串数组

在这里插入图片描述

  1. 14.字符串其它操作
    public static void String_others() {
    
    
        /*
        字符串其它操作
         */
        String str = "HEllo";
        System.out.println(str.toLowerCase());// 全部转换为 小写
        System.out.println(str.toUpperCase());// 全部转换为 大写
        System.out.println(str.length());
        System.out.println(str.isEmpty());// ""空;null指向为空
    }

hello
HELLO
5
false
  1. StringBuilder和StringBuilder
/**
     * String、StringBuffer、StringBuilder的区别:
     * 1.String的拼接会产生大量的临时变量,StringBuilder和StringBuffer不会
     * Spring拼接会被优化为SpringBuilder
     *
     *
     * String的内容不可修改,StringBuffer与StringBuilder的内容可以修改.
     * StringBuffer与StringBuilder大部分功能是相似的
     * StringBuffer采用同步处理,属于线程安全操作;而StringBuilder未采用同步处理,属于线程不安
     * 全操作
     */
    public static void Buffer_Builder() {
    
    
        /*
        StringBuilder和StringBuilder
         */
        String str = "";
        for (int i = 0; i < 3; i++) {
    
    
            str += i;
        }

        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < 4; i++) {
    
    
            stringBuilder.append(i + "");
        }

        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("Hello");
        System.out.println(stringBuffer.reverse());
        System.out.println(stringBuffer.delete(0, 1));
        System.out.println(stringBuilder.insert(0, "GG"));
    }

olleH
lleH
GG0123

源码说明StringBuilder不存在synchronized修饰来限定线程同步所以不安全而StringBuffer是安全的
在这里插入图片描述
在这里插入图片描述

String hello说明创建了一个hello的字符串
new:说明创建了一个对象,后边的StringBuilder说明是StringBuilder对象
invokespecial:说明调用了什么方法,后边的StringBuilder说明调用了StringBuilder方法;后边的几个调用的是StringBuilder的append方法
最后因为要打印,所以需要经过otString转换后才能输出字符串

此处的反编译是代码中StringBuilder和StringBuffer代码中的部分反编译结果图

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45364220/article/details/113191588