Java中String知识总结


Sting类不管在任何一个语言中都是非常重要的,我们在很多地方都会使用它,我们需要熟练掌握。

String的常见创建方式

        //方式一
        String str1="hello";
        
        //方式二
        String str2=new String("hello");
        
        //方式三
        char[] ch={'h','e','l','l','o'};       
        String str3=new String(ch);

三种方式在内存中的分布如图
在这里插入图片描述

字符串比较

==比较

比较两个引用是否是指向同一个对象

String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2);
// 执行结果
true 

str1 和 str2 是指向同一个对象的. 此时如 “Hello” 这样的字符串常量是在 字符串常量池

String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2);
// 执行结果
false

通过 String str1 = new String(“Hello”); 这样的方式创建的 String 对象相当于再上另外开辟了空间来存储"Hello" 的内容, 也就是内存中存在两份 "Hello

总结:
String 使用 == 比较并不是在比较字符串内容, 而是比较两个引用是否是指向同一个对象

equals比较

Java 中要想比较字符串的内容, 必须采用String类提供的equals方法

String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1.equals(str2));
 // 或者这样写也行
// System.out.println(str2.equals(str1));
// 执行结果
true

equals 使用注意事项
现在需要比较 str 和 “Hello” 两个字符串是否相等, 我们该如何来写呢?

String str = null;
// 方式一
System.out.println(str.equals("Hello"));  // 执行结果 抛出 java.lang.NullPointerException 异// 方式二
System.out.println("Hello".equals(str));  // 执行结果 false

我们更推荐使用 “方式二”. 一旦 str 是 null, 方式一的代码会抛出异常, 而方式二不会(“Hello” 这样的字面值常量, 本质上也是一个 String 对象, 完全可以使用 equals 等 String 对象的方法)

字符常量池

String类的设计使用了共享设计模式(可以理解为现在的共享单车,如果我们想用的话就在外面直接扫一辆单车直接用就行了(从常量池中取),不用我们再买一辆新的自行车(自己new一个新的对象赋值),大大方便了我们的使用)

在JVM底层实际上会自动维护一个对象池(字符串常量池)

  • 如果现在采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中.
  • 如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如若有指定内容,将直接进行引用。
  • 如若没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用

我们一般采取直接赋值方式创建 String 对象

字符串不可变

字符串是一种不可变对象. 它的内容不可改变.
String 类的内部实现也是基于 char[] 来实现的, 但是 String 类并没有提供 set 方法之类的来修改内部的字符数组.

String str = "hello" ;
str = str + " world" ;
str += "!!!" ;
System.out.println(str);
// 执行结果
hello world!!!

形如 += 这样的操作, += 之后 str 打印的结果确实是变了, 但是不是 String 对象本身发生改变, 而是 str 引用到了其他的对象。

那么如果实在需要修改字符串, 例如, 现有字符串 str = “Hello” , 想改成 str = “hello” , 该怎么办?

  • 1)常见办法: 借助原字符串, 创建新的字符串
String str = "Hello";
str = "h" + str.substring(1);
System.out.println(str);
// 执行结果
hello
  • 2)反射
    使用 “反射” 这样的操作可以破坏封装, 访问一个类内部的 private 成员

为什么 String 要不可变?(不可变对象的好处是什么?)

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

字符、字节与字符串

字符与字符串

字符串内部包含一个字符数组,String 可以和 char[] 相互转换.

常用的一些方法

  • toCharArray()将此字符串转换为新的字符数组并返回
  • charAt() 截取一个字符
  • String()数组转字符串
  • valueOf(char[])数组转字符串
  • copyValueOf(char[])数组转字符串

字节与字符串

字节常用于数据传输以及编码转换的处理之中,String 也能方便的和 byte[] 相互转换(一般在网络方面使用)

常用的一些方法

  • getBytes()将字符串以字节数组的形式返回
  • getBytes(String charsetName)throws UnsupportedEncodingException编码转换处理

字符串常见的操作

这里我只列举了一点点,详情的话大家可以参考这位博主的文章java String类的常用方法

字符串比较

  • equals()和equalsIgnoreCase() 比较两个字符串(ignore不区分大小写)
  • compareTo()和compareToIgnoreCase() 比较字符串

字符串查找

  • 字符串查找,最好用最方便的就是contains()
  • startsWith()方法判断是否以指定字符开头
  • endWith()方法决定是否以指定字符结尾
  • indexOf() 查找字符或者子串第一次出现的地方。
  • lastIndexOf() 查找字符或者子串最后一次出现的地方

字符串替换

  • replaceAll() 替换所有指定内容
  • replaceFirst()替换首个内容

注意事项: 由于字符串是不可变对象 , 替换不修改当前字符串, 而是产生一个新的字符串

字符串拆分

  • split(String regex)将字符串全部拆分
  • split(String regex,int limit)将字符串部分拆分,切分该数组长度的就是limit的最大值

拆分是特别常用的操作. 一定要重点掌握. 另外有些特殊字符作为分割符可能无法正确切分, 需要加上转义.

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

注意事项:

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

多次拆分

String str = "name=zhangsan&age=18" ;
String[] result = str.split("&") ;
for (int i = 0; i < result.length; i++) {
 String[] temp = result[i].split("=") ;
 System.out.println(temp[1]);
} 
运行结果
zahngsan
18

split(String regex,int limit)

        String str = "aaaaaa=bbbbbb=cccccc=ddddd" ;
        String[] strings=str.split("=",2);
        for(int i=0;i<strings.length;i++) {
            System.out.println(strings[i]);
        }
运行结果为
aaaaaa
bbbbbb=cccccc=ddddd

limit给2的话数组的长度便会是2(会切分为两部分)

字符串截取

从一个完整的字符串之中截取出部分内容。可用方法如下

  • String substring(int beginIndex)从指定索引截取到结尾 String
  • substring(int beginIndex,int endInx)截取部分内容
String str = "helloworld" ;
System.out.println(str.substring(5));
System.out.println(str.substring(0, 5));
输出结果
world
hello

注意事项:

  • 索引从0开始
  • 注意左闭右开的写法, substring(0, 5) 表示包含 0 号下标的字符, 不包含 5 号下标

其他常用的方法

  • String trim()去掉字符串中的左右空格,保留中间的空格
  • String toUpperCase()字符串转大写
  • String toLowerCase()字符串转小写
  • public native String intern()字符串入池
  • String concat(String str)字符串连接,等同于“+‘’ 但不入池
  • int length()取字符串的长度
  • boolean isEmpty()判断是否为空字符串,但不是null,而是长度为0

String、StringBuffer 和 StringBuilder

首先来回顾下String类的特点:
任何的字符串常量都是String对象,而且String的常量一旦声明不可改变,如果改变对象内容,改变的是其引用的指向而已。通常来讲String的操作比较简单,但是由于String的不可更改特性,为了方便字符串的修改,提供StringBuffer和StringBuilder类。

String、StringBuffer 和 StringBuilder之间的转换

注意:String和StringBuffer类不能直接转换。如果要想互相转换,可以采用如下原则:(String和StringBuilder类似)

  • String变为StringBuffer:利用StringBuffer的构造方法或append()方法
    StringBuffer定义了三个构造函数:
      StringBuffer()
      StringBuffer(int size)
      StringBuffer(String str)
      StringBuffer(CharSequence chars)
  • StringBuffer变为String:调用toString()方法

String、StringBuffer 和 StringBuilder之间的区别

String 和 StringBuilder StringBuffer 区别:

  • 后两者包含了一些String没有的方法 比如reverse方法
  • 后两者是可变的,String是不可变的。String的每次拼接,都会产生新的对象,后两者每次的拼接都返回的是this
  • StringBuilder 之间 StringBuffer 区别:

StringBuilder和String 出现在单线程情况下
StringBuffer因为有synchronized关键字 所以一般出现多线程情况下。

  • StringBuilder和 String之间有啥区别!!

String的拼接 + 会被优化 优化为StringBuilder . append了 !!!
在循环当中 不可以使用String直接进行拼接 这样会产生大量的临时对象(包括优化之后StringBuilder对象)

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值