【详细了解String类】——Java基础

目录

一.字符串的创建

字面量

二.字符串的内存布局

三. equals方法比较字符串是否相等

四.字符串的常量池

使用intern() 手工入池

五.字符串的不可变性

① 例

② 例

修改字符串本身

SrtingBuilder的一些特殊方法

六.String与char [ ] 类型和byte[ ]的转换

七.字符串常用操作

字符串的比较

字符串查找

字符串替换

字符串拆分

字符串截取

其他操作方法


一.字符串的创建

  1. 直接赋值  String str = " hello world " ; //推荐使用
  2. 通过new来创建字符串对象    String str =  new  String(" hello world " );
  3. 通过char数组来创建字符串对象  char[ ]  data ={ 'y', 'e', 's' }; String str =  new  String(data );

字面量

直接写出来的值就称其为字面量,例如数字10就是整型字面量——默认是int类型;10.2就是浮点型字面量——默认是double类型;上面字符串的第一种创建法创建的" hello world "就是字符串字面量——默认是String类型。

二.字符串的内存布局

String str = "hello world";
String str1 = str;

这两行代码在内存中中如何存储呢?

所以,它们在空间中如下图存储,相当于一个对象有两个引用

 

三. equals方法比较字符串是否相等

对于基本数据类型, == 比较的是两个变量的值

而对于引用数据类型,引用变量保存的是堆内存的地址而不是值,不能使用 == 比较内容是否相等

public static void main(String[] args) {
    String str = new String("hello");
    String str1 = new String("hello");
    System.out.println(str == str1);//输出false
    System.out.println(str.equals(str1));//输出true
}

假设用户输入一个字符串str,要判断str的内容是否是“hello” ,我们可以使用下面两种语句:

  1. str.equals("hello");
  2. "hello".equals(str);

这里推荐使用第二种语句,equals方法是通过对象调用的,它是一个成员方法。使用第一种方法是,如果用户输入为空就会报错。因为null对象不能调用成员方法,必须通过具体对象来调用成员方法。

 static String str ;
    public static void main(String[] args) {

        System.out.println(str.equals("hello"));
    }

 把输出语句换成第二种方法,输出结果就为false,因为"hello"是字符串的字面量,也就是字符串的匿名对象。

 System.out.println("hello".equals(str));

四.字符串的常量池

 public static void main(String[] args) {
        String str = "yes";
        String str1 = "yes";
        String str2 = "yes";
        System.out.println(str == str1);
        System.out.println(str1 == str2);
}输出true
     true

上面我们说过,使用==比较的是字符串的地址,那么也就是说str、str1、str2他们指向的同一个地址。这是为什么呢?

JVM会对字符串创建一个字符串的常量池,使用直接赋值法创建字符串时,字面量是第一次出现,JVM就会创建一个String对象并且扔到常量池中。当字面量再次出现时,并不会创建新的对象,而是复用已有的对象

我们可以理解“”就是复用已有变量,保证效率

        String str = "yes";
        String str1 = new String("yes");
        System.out.println(str == str1);
        //结果为false

我们知道,有new就有新空间,str1没有入池。只有直接赋值法创建的变量才会入池 

使用intern() 手工入池

        String str = new String("hello").intern();
        String str1 = "hello";
        System.out.println(str == str1);
        //结果为true

为什么推荐使用直接赋值法创建对象呢?我们分析一下下面这个语句一共创建了几个对象

String str1 = new String("yes");

 

 也就是说,一共创建了两个对象

 

 new了之后,str就指向了下面的空间,之前的空间就没有没有任何的引用指向,变成了垃圾空间。所以每次通过new来创建字符串对象 就会创建两个对象,其中一个是垃圾空间。因此,更推荐使用直接赋值法。

五.字符串的不可变性

① 例

        String str = "hello";
        str = "world";
        System.out.println(str);
        //输出:world

 这里输出不是最初的str,为什么说字符串“不可变”呢?让我们看看它们在空间上如何变化

 str指向从“hello”变成“world”,而原字符串并没有任何改变。

② 例

static String str = "hello";
   static char[] data = {'a','b','c'};
    public static void main(String[] args) {

        change(str,data);
        System.out.println(str);
        System.out.println(data);

    }
    public static void change(String s ,char[] a){
        s = "world";
        a[0] = 'g';
    }

输出结果:

 

 

调用change方法时,实参的值传给了形参,当s=world之后,s就不再指向"hello"。而数组data传给a之后,在原数组上做出了修改,因为s和data指向的同一空间,所以对数组的改变main方法中data是可见的。

字符串本身是不变的,变的只引用的指向,这就是字符串的不可变性。

修改字符串本身

想要修改字符串变量的内容,只能通过反射破坏封装

 public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        String str = "hello";
        //通过反射获取到String类的value数组
        Field field = String.class.getDeclaredField("value");
        //value的private定义取消
        field.setAccessible(true);
        //获取到str对象内部的value数组
        char[] value = (char[]) field.get(str);
        value[0] = 'H';
        System.out.println(str);
    }
//输出:Hello

当字符串需要频繁修改时,使用两个sb类:

  • StringBuffer:线程安全
  • SrtingBuilder:线程不安全

两个类在使用上没有任何区别,通常使用SrtingBuilder,它的效率高,使用方法如下

public static void main(String[] args) {
    //String -> StringBuilder
    //方法一,通过构造方法转
    StringBuilder sb = new StringBuilder("hello");
    //方法二,调用append方法
    sb.append("world");
    sb.append("!!!");
    //StringBuilder -> String
    String str = sb.toString();
    System.out.println(sb);

}
//输出结果:helloworld!!!

SrtingBuilder的一些特殊方法

因为SrtingBuilder可以修改内容,String类内容无法修改,所以它具有一些String不具有的一些方法。

1.reserve方法——反转

public static void main(String[] args) {
        StringBuilder sb = new StringBuilder("hello world");
        System.out.println(sb.reverse());
        System.out.println(sb);
    }
//结果:
dlrow olleh
dlrow olleh

可以看到sb本身也被修改了 

2.delete( int start, int end )——删除指定范围的内容

         StringBuilder sb = new StringBuilder("hello world");
        sb.delete(5,10);
        System.out.println(sb);
        //输出:hellod

 从输出结果可以看到索引为10的‘d’并没有被删除(要记得索引下标是从0开始的),也就是说这是一个左闭右开区间 [5,10) 。Java中区间的取值一般来说都是左闭右开区间。

3.insert ( int start ,插入的数据 )在索引为start的位置插入数据

        StringBuilder sb = new StringBuilder("hello world");
        //System.out.println(sb.reverse());
        sb.insert(5,"呵呵");
        System.out.println(sb);
        //输出结果:hello呵呵 world

六.String与char [ ] 类型和byte[ ]的转换

1.String -> char[ ] 

        String str  = "hello";
        char[] a = str.toCharArray();
        System.out.println(Arrays.toString(a));
        //输出:[h, e, l, l, o]

 2.获取字符串中索引下标对应的字符,通过遍历也可实现String -> char[ ] 

        String str  = "hello";
        char b = str.charAt(1);
        System.out.println(b);
        //输出:e

3.char[ ]  -> String

        char[] a = {'a','b','c','1','2'};
        String str =new  String(a);//全部转换
        String str1 = new String(a,1,3);//部分转换
        System.out.println(str);
        System.out.println(str1);
        //结果:abc12
               bc1

4.String -> byte[ ] 

        String str  = "hello world";
        byte[] b = str.getBytes();
        System.out.println(Arrays.toString(b));
//输出结果:[104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]

**char通常是处理文本内容时使用,byte一般在网络传输或者输入输出中(读写文件)使用例如判断网速时默认单位就是byte。

七.字符串常用操作

字符串的比较

  1. equals方法
  2. equalsIgnoreCase方法——不区分大小写的比较
  3. compareTo方法——比较两个字符串大小关系
        String str = "hello";
        String str1 = "Hello";
        System.out.println(str.equals(str1));
        System.out.println(str.equalsIgnoreCase(str1));
        System.out.println(str.compareTo(str1));
//输出结果:
false
true
32

*输出的32是大小写字母的ASCLL相差的单位

字符串查找

上表中最常使用的是第一个方法,代码示例如下:

 

 

        String str = "hello";
        System.out.println(str.contains("ell"));
        System.out.println(str.contains("world"));
        //结果:
        true
        false

其他的几种方法读者下去可以多多尝试

字符串替换

  • replaceAll (a , b )——将字符串中所有a换成b
  • replaceFirst ( a, b )——替换首个内容
        String str = "hello";
        String str1 = str.replaceAll("l","h");
        String str2 = str.replaceFirst("l","h");
        System.out.println(str1);
        System.out.println(str2);
        //结果:hehho
               hehlo

要记住,String的所有修改操作的内部都是创建一个新的字符,一定要记住字符串的不可变性!!!

字符串拆分

  • public String[ ] split (String regex ) ——将全部字符串拆分
  • public String[ ] split (String regex,int limit)——部分拆分,限制个数
        String str = "hello Java I came";
        String[] str1 = str.split(" ");//按空格拆分
        String [] str2 = str.split(" ",2);//按空格拆成2个
        System.out.println(Arrays.toString(str1));
        System.out.println(Arrays.toString(str2));
//输出结果:[hello, Java, I, came]
           [hello, Java I came]

 注意事项:

       一些特殊字符作为分割符号时要转义处理,|、*、+ 前面加上“\”,如果是“.” 前面加上“\\”

        String str = "192.168.1.1";
        String[] sr1 = str.split("\\.");
        System.out.println(Arrays.toString(sr1));
        //输出结果:[192, 168, 1, 1]

字符串截取

  • substring方法
        String str = "helloworld";
        System.out.println(str.substring(5));//从索引开始截取到结尾
        System.out.println(str.substring(5,8));//截取部分,左闭右开区间
//结果:world
       wor

其他操作方法

 

 有关String类的内容就到这里啦,一定要理解字符串的不可变性!!!

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值