Java中的String类详解

目录

String类的创建:

关于String类的典型内存分布 

.intern()的使用 

字符串的不可变性

字符、字节和字符串的转换

字符串的常用操作

 StringBuffer和StringBuilder

字符串典型例题


String类的创建:

字符串就是用双引号引起来的一串字符。创建方式主要有三种:

 String str = "abcdef";  //1、直接赋值
 String str2 = new String("abcdef");  //2、new一个String对象
 char[] array = {'a', 'b', 'c', 'd', 'e', 'f'};  //3、通过字符数组
 String str3 = new String(array);

内存中的分布:

首先直接赋值的方式:字符常量都存放在常量池中,且仅此一份。

第二种方法:String底层实现有一个value[]数组,

 拿到常量池中已经存在的的abcdef构造了String对象,String对象中有一个value[]数组,来保存abcdef的地址。产生了两个对象。

第三种方法:

String底层的构造方法如下图:

关于String类的典型内存分布 

ps:==相对于基本类型比较值是否相等,相对于引用类型是比较地址是否相等。

        String str1 = "abcdef";
        String str2 = new String("abcdef");
        System.out.println(str1 == str2); //1、false 上图可表明

        String str3 = "abc" + "def";
        System.out.println(str1 == str3); //2、true "abc" 和 "def"
        都是字符常量,在编译时已经合并为abcdef,常量池中相同的字符串只能存在一份,因此str1和str3指 
        向同一块空间

        String str4 = "abc" + new String("def");
        System.out.println(str1 == str4); //3、false

        String str5 = "abc";
        String str6 = "def";
        String str7 = str5+str6;
        System.out.println(str1 == str7); //false 和第三个思想类似

        String str8 = str5 + new String("def");
        System.out.println(str1 == str8); //false 和第三个思想类似

第三个比较令人疑惑,其实它在内存中如下分布:

 

.intern()的使用 

 String str1 = "abcdef";
 String str2 = new String("abcdef").intern();
 System.out.println(str1 == str2);

天呐,上面代码运行出来竟然是true。。intern();方法还是非常强大的。作用为手动入池。

1、intern() 方法是一个native方法,底层是由C/C++实现的。

 2、如果常量池当中存在将要入池的字符串,直接将常量池当中的字符串常量的地址返回
      如果常量池不存在,那么在常量池当中将该字符串入池。

字符串的不可变性

一段代码:

 String str = "hello";
 str = str + "world";
 str += "!!";
 System.out.println(str);

这个代码打印出来肯定是 helloworld!! ,但是并不是修改了原来的str中的值,而是创建了新的对象,体现了字符串的不可变性。而且每次拼接都会产生新的对象。

那么为什么String要不可变: 
1. 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑何时深拷贝字符串的问题了
2. 不可变对象是线程安全的
3. 不可变对象更方便缓存hash code,作为key可以更高效的保存在Hash Map中 

如何有一个字符串"Hello",一定要把它改为"hello",那么就要用到反射了,反射需要先得到Class对象,存放在方法去,存放的是类的信息。具体方法如下:

  public static void main(String[] args) throws NoSuchFieldException , 
  IllegalAccessException{
        String str = "Hello"; //new String()
        Class cls = String.class; //获取class对象
        Field field = cls.getDeclaredField("value"); //把str中的value获取到
        field.setAccessible(true);
        char[] value = (char[])field.get(str);
        value[0] = 'h';
        System.out.println(str);
    }

字符、字节和字符串的转换

字符串和字符之间的转化:

1.字符转化为字符串

 char[] array = {'a', 'b', 'c', 'd', 'e', 'f'};  
 String str3 = new String(array);

2.字符串转化为字符

String str = "abcdef";
char[] array = str.toCharArray();

字符串和字节的转化:

1.字节转化为字符串

byte[] bytes = {97, 98, 99, 100};
String str = new String(bytes);
System.out.println(str); //abcd

2.字符串转化为字节

 String str1 = "白";
 byte[] bytes1 = str1.getBytes("Unicode");
 System.out.println(Arrays.toString(bytes1)); //获取字符串的编码方式

byte[] and char[] 的适用范围:
byte[] 是把 String 按照一个字节一个字节的方式处理, 这种适合在网络传输, 数据存储这样的场景下使用. 更适合 针对二进制数据来操作
char[] 是吧
String 按照一个字符一个字符的方式处理, 更适合针对文本数据来操作, 尤其是包含中文的时候

字符串的常用操作

1、字符串比较:

        String str = "Hello";
        String str1 = "hello";
        System.out.println(str.equals(str1));  //false
        System.out.println(str.equalsIgnoreCase(str1)); //true
        System.out.println(str.compareTo(str1)); //-32

字符串比较有三种方法,equals是比较字符串的值是否相等区分大小写,.equalsIgnoreCase不区分大小写。而compareTo()返回一个整型。

2、字符串查找

        String str = "abcdefg";
        //是否包含 底层调用indexOf()函数
        System.out.println(str.contains("def")); //true

        //查找子串-》返回下标
        System.out.println(str.indexOf("bcd")); //1

        //从后往前查找子串-》返回下标
        System.out.println(str.lastIndexOf("cd")); //2

        //判断是否以指定字符串开头
        System.out.println(str.startsWith("ab")); //true

        //判断是否以指定字符串结束
        System.out.println(str.endsWith("ef")); //false

3、 字符串替换

        String str = "abcabcba";
        System.out.println(str.replace('a','A')); //AbcAbcbA
        System.out.println(str.replace("ab","##")); //##c##cba
        System.out.println(str.replaceAll("ab","##")); //##c##cba
        System.out.println(str.replaceFirst("abc","**")); //**abcba

4、字符串拆分

        String str = "a,bc ab,c b,a";
        //[a,bc, ab,c, b,a]
        String[] string = str.split(" "); //以空格为间隔符进行拆分
        for (int i = 0; i < string.length; i++) {
            String[] string2 = string[i].split(",");
            // [a, bc]
            //[ab, c]
            //[b, a]
            System.out.println(Arrays.toString(string2));
       }
  String str = "a,bc ab,c b,a";
        //[a,bc, ab,c,b,a]
  String[] string = str.split(" ",2); //所要分得的组数最大是2

 注意有些特殊字符作为分隔符可能无法正确拆分,需要加上转义。

        String str = "193.168.1.1";
        String[] strings = str.split("\\.");
        for (int i = 0; i < strings.length; i++) {
            System.out.println(strings[i]);
        }

注意:第一个\表示把 "\\" -> "\",第二个"\"是正则表达式"\." -> "." 
 字符"|","*","+"也是这样的规则,并且当一个字符串中有多个分隔符时,可以用"|"作为连字符。

5、字符串截取

        String str = "abcdefg";
        System.out.println(str.substring(2)); //cdefg
        System.out.println(str.substring(2,5)); //左闭右开   cde

6、其他操作 

1)去掉字符串左右的空格,保留中间空格

        String str = "   abc d e     ";
        System.out.println(str.trim()); //abc d e

2)大小写转换

        String str = "abCDEFg";
        System.out.println(str.toUpperCase()); //ABCDEFG
        System.out.println(str.toLowerCase()); //abcdefg

3)字符串入池操作

        char[] array = {'a', 'b', 'c'};
        String str = new String(array);
        str.intern();

 4)字符串连接,等同于“+”,不入池

        String str = "hello";
        System.out.println(str.concat("Java")); //helloJava

 5)判断字符串是否为空,取得字符串长度

        String str = "";
        System.out.println(str.isEmpty()); //true
        System.out.println(str.length()); // 0 注意是方法

 StringBuffer和StringBuilder

任何字符串常量就是String对象,而且String的常量一旦声明不可改变,如果改变对象内容,改变的只是引用的指向。由于字符串的不可变性,为了方便字符串的修改,提供StringBuffer和StringBuilder类,这两个大部分功能是相同的。

String的拼接底层会优化为StringBuilder

   public static void main(String[] args) {
        String str = "abc";
        String str2 = str + "def";
        System.out.println(str2);
    }

StringBuilder的拼接并没有产生新的对象,是在原来对象进行修改。append();方法实现

    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("abc");
        System.out.println(sb); //abc
        sb.append("java"); 
        System.out.println(sb); // abcjava
    }

ps:解释String、StringBuffer、StringBuilder的区别

1、String的内容不可修改,StringBuffer、StringBuilder的内容可以修改。
2、StringBuffer、StringBuilder使用方法是一样的,但是StringBuffer线程安全,String和StringBuilder线程不安全
3、String之间的拼接底层优化为了StringBuilder(append();方法)。StringBuffer、StringBuilder的append()不会产生新的对象(return this)

注意:String和StringBuffer不能直接转化,如果想要互相转化,可以:
String变为StringBuffer:利用StringBuffer的构造方法或append()方法
StringBuffer变为String:调用toString方法

字符串典型例题

1、输入两个字符串,需要无冗余拼接

   
   public static String myAppend(String str) {
        //分割
         String[] strs = str.split(" ");
        //String ret = "";
        //for(String s : strs) {
        //    ret += s;
        //}
        //return ret;

        StringBuilder sb = new StringBuilder();
        for(String s : sb) {
           sb.append(s);
        }
        return sb.toString();
       
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String str = scanner.nextLine();
        System.out.println(myAppend(str));
    }

2、将字符串进行逆置

    //逆置字符串
    public static String reverse(String string) {
        char[] array = string.toCharArray();
        int left = 0;
        int right = array.length-1;
        while (left < right) {
            char tmp = array[left];
            array[left] = array[right];
            array[right] = tmp;
            left++;
            right--;
        }
        return String.copyValueOf(array);
    }

    public static void main(String[] args) {
        String str = "abcdef";
        String ret = reverse(str);
        System.out.println(ret);
    }

3、给定一个字符型的数组chas和一个整数size,请把大小为size的左半区整体右移到右半区,右半区整体移动到左边。

逆置前半部分-》逆置后半部分-》全部逆置

    public static String reverse2(String str, int start, int end) {
        char[] array = str.toCharArray();
        while (start < end) {
            char tmp = array[start];
            array[start] = array[end];
            array[end] = tmp;
            start++;
            end--;
        }
        return String.copyValueOf(array);
    }

    public static String fun(String str, int k) {
        str = reverse2(str, 0, k-1);
        str = reverse2(str, k,str.length()-1);
        str = reverse2(str,0,str.length()-1);
        return str;
    }

    public static void main(String[] args) {
        String str = "abcdef";
        System.out.println(fun(str,3)); //defabc
    }

4、字符串的转化(压缩) aabbccda -》 2a2b2c1d1a

    //字符串的转化(压缩) aabbccda -》 2a2b2c1d1a
    public static String changeString(String str) {
        char ch = str.charAt(0);
        StringBuilder stringBuilder = new StringBuilder();
        int count = 1;
        for (int i = 1; i < str.length(); i++) {
            if (ch == str.charAt(i)) {
                count++;
            } else {
               stringBuilder.append(count).append(ch);
               ch = str.charAt(i);
               count = 1;
            }
        }
        return stringBuilder.append(count).append(ch).toString(); //拷贝最后一组
    }

    public static void main17(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String str = scanner.next();
        System.out.println(changeString(str));
    }

5、i am student -> stduent am i

    //i am student -> stduent am i
    //先整体逆置,再单词逆置
    public static String reverseString(char[] array, int start, int end) {
        while (start < end) {
            char tmp = array[start];
            array[start] = array[end];
            array[end] = tmp;
            start++;
            end--;
        }
        return String.copyValueOf(array);
    }

    public static String fun(String str) {
        char[] array = str.toCharArray();
        //整体逆置
        reverseString(array,0,str.length()-1);
        //逆置单词
        int i = 0;
        int j = 0;
        while (i < array.length) {
            if (array[i] == ' ') {
                i++;
                j++;
            } else if (j == array.length || array[j] == ' ') {
                reverseString(array,i,j-1);
                i = ++j;
            } else {
                j++;
            }
        }
        return String.copyValueOf(array);
    }

    public static void main(String[] args) {
        String str = "i am stdent";
        System.out.println(fun(str));
    }
发布了51 篇原创文章 · 获赞 14 · 访问量 2315

猜你喜欢

转载自blog.csdn.net/qq_41185460/article/details/103267357