不就是Java吗之String类 PartI

一、String的介绍

C语言中,是没有字符串类型的,但是有字符串

char* p = "hello";

Java中,是有字符串这种数据类型的,但是他不是所谓的以\0为结尾的,是通过长度判断字符串是否结尾

二、常用方法

2.1 字符串构造

  1. 使用常量串构造

    public class TestDemo1 {
        public static void main(String[] args) {
            //使用常量串构造
            String str1 = "hello";
            System.out.println(str1);
        }
    }
    
  2. 直接new String对象

    public class TestDemo1 {
        public static void main(String[] args) {
            //直接new String对象
            String str2 = new String("hello2");
            System.out.println(str2);
        }
    }
    
  3. 使用字符数组进行构造

    public class TestDemo1 {
        public static void main(String[] args) {
            //使用字符数组进行构造
            char[] array = {'h','e','l','l','o','3'};
            String str3 = new String(array);
            System.out.println(str3);
        }
    }
    

注意:

  1. String是引用类型,内部并不存储字符串本身,其实底层就是数组

    image-20220606154254316

  2. 内存分配图

    public class TestDemo1 {
        public static void main(String[] args) {
            String str1 = new String("hello");
            String str2 = new String("world");
            String str3 = str1;
    
            System.out.println(str1);
            System.out.println(str2);
            System.out.println(str3);
        }
    }
    

    image-20220606154820236

    image-20220606155539670

  3. 两个方法

    1. s1.length():获取字符串长度

      注意:要带上后面的括号

      public class TestDemo1 {
          public static void main(String[] args) {
              String str1 = new String("hello");
      
              System.out.println(str1.isEmpty());
              System.out.println("hello".length());
          }
      }
      
      
    2. s1.isEmpty():如果字符串长度为0,返回true,否则返回false

      public class TestDemo1 {
          public static void main(String[] args) {
              String str1 = new String("hello");
      
              System.out.println(str1.isEmpty());
          }
      }
      
      

2.2 String对象的比较

2.2.1 ==

比较是否引用同一个对象

对于内置类型,比较的是值是否相等

对于引用类型,比较的是引用中的地址是否相同

public class TestDemo2 {
    public static void main(String[] args) {
        //只要你进行new,就会开辟新的内存空间
        String str1 = new String("hello");
        String str2 = new String("hello");
        String str3 = new String("world");

        String str4 = str1;

        System.out.println(str1 == str2);//false
        System.out.println(str1 == str3);//false
        System.out.println(str1 == str4);//true
    }
}

2.2.2 boolean equals(Object o)

比较两个字符串是否相等:按照字典序进行比较

字典序:就是按照字典中出现的先后顺序进行排序。

String类重写了父类当中的equals方法,以前equals是按照地址进行比较的,被equals重写之后按照以下规则进行比较

public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

image-20220606164654703

这个方法的使用:

public class TestDemo3 {
    public static void main(String[] args) {
        String str1 = new String("hello");
        String str2 = new String("hello");
        String str3 = new String("Hello");

        System.out.println(str1.equals(str2));//true
        System.out.println(str1.equals(str3));//false
    }
}

2.2.3 int compareTo(String s)

比较两个字符串的大小:按照字典序进行比较

  1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符的大小差值
  2. 如果前k个字符相等(k为两个字符长度最小值),返回值两个字符串长度差值
public class TestDemo4 {
    public static void main(String[] args) {
        String str1 = new String("abc");
        String str2 = new String("ac");
        String str3 = new String("abc");
        String str4 = new String("abcdef");

        System.out.println(str1.compareTo(str2));//-1 -> 不同输出字符差值-1
        System.out.println(str1.compareTo(str3));//0 -> 相同输出 0
        System.out.println(str1.compareTo(str4));//-3 -> 前k个字符完全相同,输出长度差值-3
    }
}

2.2.4 int compareToIgnoreCase(String str)

int compareTo(String s)相同,但是这个忽略大小写

public class TestDemo4 {
    public static void main(String[] args) {
        String str1 = new String("abc");
        String str2 = new String("ac");
        String str3 = new String("abc");
        String str4 = new String("abcdef");

        System.out.println(str1.compareToIgnoreCase(str2));//-1 -> 不同输出字符差值-1
        System.out.println(str1.compareToIgnoreCase(str3));//0 -> 相同输出 0
        System.out.println(str1.compareToIgnoreCase(str4));//-3 -> 前k个字符完全相同,输出长度差值-3

    }
}

2.3 字符串查找

2.3.1 char charAt(int index)

返回index位置上字符,如果index为负数或者越界,抛出IndexOutOfBoundsException异常

public class TestDemo1 {
    public static void main(String[] args) {
        String str = "hello";
        char ch = str.charAt(1);
        System.out.println(ch);//e
    }
}

注意:下标必须合法

image-20220606204512097

2.3.2 int indexOf()

四种形式:

  1. int indexOf(int ch):返回ch第一次出现的位置,没有返回-1
  2. int indexOf(int ch,int fromIndex):从fromIndex开始,返回ch第一次出现的位置,没有返回-1
  3. int indexOf(String str):返回字符串str第一次出现的位置,没有返回-1
  4. int indexOf(String str,int fromIndex):从fromIndex开始,返回str第一次出现的位置,没有返回-1
public class TestDemo2 {
    public static void main(String[] args) {
        String str = "hello";

        int index1 = str.indexOf('h');
        System.out.println(index1);//0

        int index2 = str.indexOf('o',2);
        System.out.println(index2);//4

        int index3 = str.indexOf("ll");
        System.out.println(index3);//2

        int index4 = str.indexOf("ll",1);
        System.out.println(index4);//2
    }
}

2.3.3 int lastIndexOf()

四种形式:

  1. int lastIndexOf(int ch):从后往前找,返回ch第一次出现的位置,没有返回-1
  2. int lastIndexOf(int ch,int fromIndex):从fromIndex位置开始找,从后往前找ch第一次出现的位置,没有返
    回-1
  3. int lastIndexOf(String str):从后往前找,返回str第一次出现的位置,没有返回-1
  4. int lastIndexOf(String str,int fromIndex) :从fromIndex位置开始找,从后往前找str第一次出现的位置,没有返
    回-1
public class TestDemo3 {
    public static void main(String[] args) {
        String str = "hello";

        int index1 = str.lastIndexOf('h');
        System.out.println(index1);//0

        int index2 = str.lastIndexOf('l',4);
        System.out.println(index2);//3

        int index3 = str.lastIndexOf("ll");
        System.out.println(index3);//2

        int index4 = str.lastIndexOf("ll",4);
        System.out.println(index4);//2
        
        int index5 = str.lastIndexOf('l',2);//从2下标往前找->找不到->返回-1
        System.out.println(index5);//-1
    }
}

2.4 转化

2.4.1 数值和字符串转化

public class TestDemo1 {
    public static void main(String[] args) {
        int a = 10;
        String str1 = String.valueOf(a);
        System.out.println(str1);//"10:
        System.out.println(str1 + 1);//"101" -> 能证明str变成字符串了

        System.out.println("---------------");

        String str2 = "1234";
        int num1 = Integer.valueOf(str2);
        int num2 = Integer.parseInt(str2);//跟上面那种是等价的
        double num3 = Double.valueOf(str2);//也可以转换成double类型的

        System.out.println(num1);//1234
        System.out.println(num2);//1234
        System.out.println(num3);//1234.0
    }
}

2.4.2 大小写转换

需要我们知道的是:大小写转换的操作的不是原数组,是把拷贝的数组进行大小写转换的

public class TestDemo2 {
    public static void main(String[] args) {
        String str1 = "hello";
        String str2 = str1.toUpperCase();
        System.out.println(str2);//HELLO

        System.out.println("----------------");

        String str3 = "HELLO";
        String str4 = str3.toLowerCase();
        System.out.println(str4);//hello

        System.out.println("----------------");

        String str5 = "H_e!L#l%O";
        String str6 = str5.toLowerCase();//只会对字母起作用
        System.out.println(str6);//h_e!l#l%o
    }
}

2.4.3 字符串转数组

import java.util.Arrays;

public class TestDemo3 {
    public static void main(String[] args) {
        String str1 = "hello";
        char chars[] = str1.toCharArray();
        System.out.println(Arrays.toString(chars));//[h, e, l, l, o]
    }
}

2.4.4 格式化

public class TestDemo4 {
    public static void main(String[] args) {
        String str = String.format("%d-%d-%d",2022,6,6);
        System.out.println(str);//2022-6-6
    }
}

2.5 字符串替换

使用一个指定的新的字符串替换掉已有的字符串数据

regex替换成replacement

  1. String replace(String oldChar,String newChar):把oldChar替换成newChar
  2. String replaceAll(String oldChar,String newChar):替换所有的指定内容
  3. String replaceFirst(String oldChar,String newChar):替换第一个为oldChar的内容
public class TestDemo5 {
    public static void main(String[] args) {
        String str1 = "abcdabcdabcd";

        String str2 = str1.replace("ab","li");//其实跟replaceAll一样
        System.out.println(str2);//licdlicdlicd

        String str3 = str1.replaceAll("ab","kj");
        System.out.println(str3);

        String str4 = str1.replaceFirst("ab","op");
        System.out.println(str4);
    }
}

在这里,我们操作的也不是原数组.

Java中,所有对字符串本身操作的函数,都不是在原来的字符串对象上进行的操作,因为字符串是不可变的

2.6 字符串的拆分

可以将一个完整的字符串按照指定的分隔符划分为若干个子字符串。

  1. String[] split(String regex):将字符串全部拆分
  2. String[] split(String regex,int limit):将字符串以指定的格式,拆分为limit
public class TestDemo6 {
    public static void main(String[] args) {
        String str1 = "abc de f g";
        String[] strings = str1.split(" ");
        for (String s : strings) {
            System.out.println(s);
        }
    }
}

image-20220606223532358

拆分ip地址

public class TestDemo6 {
    public static void main(String[] args) {

        String str2 = "162.190.1.1";
        String[] strings = str2.split("\\.",4);//最多分割为4组
        for (String string : strings) {
            System.out.println(string);
        }
    }
}

注意事项:

  1. 字符"|“,”*“,”+"都得加上转义字符,前面加上 “\” .
  2. 而如果是 “\” ,那么就得写成 “\\” .
  3. 如果一个字符串中有多个分隔符,可以用"|"作为连字符.

举栗子:

public class TestDemo6 {
    public static void main(String[] args) {
        String str3 = "Hello0606 english&888";
        String[] strings = str3.split(" |&");
        for (String string : strings) {
            System.out.println(string);
        }
    }
}
public class TestDemo6 {
    public static void main(String[] args) {
        String str4 = "hello\\666";
        String[] strings = str4.split("\\\\");//\->\\ \\->\\\\
        for (String string : strings) {
            System.out.println(string);
        }
    }
}

多次拆分:

public class TestDemo6 {
    public static void main(String[] args) {
        String str5 = "name=zhangsan&age=18";
        String[] strings1 = str5.split("&");
        for (String str : strings1) {
            String[] strings2 = str.split("=");
            for (String str2 : strings2) {
                System.out.println(str2);
            }
        }
    }
}

2.7 字符串的截取

从一个完整的字符串之中截取出部分内容。

  1. String substring(int beginIndex):从指定索引截取到结尾
  2. String substring(int beginIndex,int endIndex):从beginIndex截取到endIndex
public class TestDemo7 {
    public static void main(String[] args) {
        String str1 = "   abde sdfi  ";
        String ret1 = str1.substring(2,7);//from to -> 前闭后开 [2,7)
        System.out.println(ret1);// abde

    }
}

2.8 trim()

String trim():去掉字符串中的左右空格,保留中间空格

public class TestDemo8 {
    public static void main(String[] args) {
        String str1 = "   abde sdfi  ";
        String ret2 = str1.trim();
        System.out.println(ret2);//abde sdfi->去掉左右两边空格,中间的不去掉
		System.out.println(ret1);//   abde sdfi  ->证明了操作字符串操作的不是本身
    }
}

2.9 字符串常量池

我们先看这段代码

public class demo_2_9 {
    public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "hello";
        System.out.println(str1 == str2);//true
    }
}

我们的猜想是:两个字符串,实际上不是新new出来的吗?new出来的不就是新的吗?那不应该是false吗.但是答案是true

我们继续看例子

public class demo_2_9 {
    public static void main(String[] args) {
        String str1 = "hello";
        String str2 = "hello";
        String str3 = new String("hello");
        System.out.println(str1 == str2);//true
        System.out.println(str1 == str3);//false
    }
}

这时候,str1str3就不相等了.这是怎么回事呢?

这一切都是字符串常量池搞的鬼.

字符串常量池一般都在堆上

image-20220607190718904

image-20220607190355206

特例:

public static void main(String[] args) {
        String str1 = "hello";
        
        String ret = "he" + "llo";//在编译的时候,这里就直接认为是hello了
        System.out.println(str1 == ret);//true
    }
public static void main(String[] args) {
        String str1 = "hello";

        String str2 = "he";
        String str3 = "llo";
        String str4 = str2 + str3;//str2 str3是变量,在编译的时候,还不知道里面是谁

        System.out.println(str1 == str4);//false
    }

记住,只要是new的,就是一定有新对象产生的

2.9.1 intern方法

public static void main(String[] args) {
        char[] ch = new char[]{'a','b','c'};
        String str = new String(ch);
        String str2 = "abc";

        System.out.println(str == str2);
    }

运行结果为:false

image-20220607192549625

图解:

image-20220607193401672

加入intern之后:

public static void main(String[] args) {
        char[] ch = new char[]{'a','b','c'};
        String str = new String(ch);
        str.intern();

        String str2 = "abc";
        System.out.println(str == str2);
    }

运行结果是true

image-20220607193600327

str.intern()的作用是把str引用的对象手动入池(当常量池没有的时候)

image-20220607194124114

2.10 字符串的不可变性

public static void main(String[] args) {
        String str = new String("hello");
        
    }

我们ctrl+单击右面的String

image-20220607194513518

image-20220607194544878

image-20220607194606586

那么我们先来了解一下final

public static void main(String[] args) {
        //String str = new String("hello");
        int[] arr = {1,2,3};
        arr = new int[]{1,2,3,4,5};
    }

这样是不报错的,代表数组的指向可以改变

加了final之后就报错了

public static void main(String[] args) {
        //String str = new String("hello");
        final int[] arr = {1,2,3};
        arr = new int[]{1,2,3,4,5};
    }

image-20220607194823168

代表array这个指向不能改变

但是我们讲了这么多,String的不可变性跟这个没关.是因为数组是被private修饰的,而官方也没设计出他的get set方法,所以不能修改

image-20220607195049350

image-20220607200057864

网上有些人说:字符串不可变是因为其内部保存字符的数组被final修饰了,因此不能改变。

这种说法是错误的,不是因为String类自身,或者其内部valuefinal修饰而不能被修改。是因为被private修饰了,根本拿不到字符串相关的函数来进行对字符串的操作,所以都是拷贝一个新数组来对新数组进行操作最后返回.

image-20220607223553640

2.11 字符串修改

我们先来看一段代码

public class TestDemo {
    public static void main(String[] args) {
        String str = "hello";
        str = str + "world";
        System.out.println(str);//helloworld
    }
}


//翻译如下
public static void main(String[] args) {
        String str = "hello";
        //str = str + "world";
        //上面那行代码的翻译
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(str);
        stringBuilder.append("world");
        str = stringBuilder.toString();
        System.out.println(str);//helloworld
    }

底层:
image-20220607202021084

如果我们再加上个"!!!"呢

public class TestDemo {
    public static void main(String[] args) {
        String str = "hello";
        str = str + "world";
        str = str + "!!!";
        System.out.println(str);//helloworld!!!
    }
}

image-20220607202326831

比如我们举个栗子:

public static void main(String[] args) {
        String str = "hello";
        for (int i = 0; i < 10; i++) {
            str += i;
        }
        System.out.println(str);
    }

这样就会产生许多许多临时对象,不推荐

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

加勒比海涛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值