Java String类

一、创建字符串

常见的构造String方法

 String str = "XXXX";
//方式一
    String str2=new String("Xxxx");
    //方式二
    char[] array = {'a','b','c'};
    String str3 =new String(array);
//方式三

String 为引用类型

复习:Java中两大类型

1. 8种内置类型:byte、short、int、long、float、double、char、boolean

2.引用类型(除了以上8种内置类型,其他均为引用类型)如:数组,String类

 String str1 = "hello";
 String str2 = str1;
 System.out.println(str2);
        //输出结果为 hello

而当改变str1时,并不会改变str2中的值

 str1="word";
        System.out.println(str2);
        //输出结果为 hello

这种操作并不是在修改字符串,而是让str1这个引用指向了一个新的String对象。

二、字符串比较相等

String类对象中使用“==”不是在比较字符串内容而是在比较两个引用是否指向同一个对象

        String str1 = "hello";
        String str2 = "hello";
        System.out.println(str1==str2);
        //输出结果为 true
        String str3 = new String("hello");
        String str4 = new String("hello");
        System.out.println(str3==str4);
        //输出结果为 false

内存布局如下图所示

在这里插入图片描述

 String类对象实质是在比较是否为同一个“储物柜”(是在比较身份,身份相同则其中放的东西肯定相同),比较“储物柜”中存放物品时需使用“equals”

String str3 = new String("hello");
        String str4 = new String("hello");
        System.out.println(str3==str4);
        //输出结果为 false
        System.out.println(str3.equals(str4));
        //输出结果为true

equals使用注意事项:

        String str1 =new String("hello");
        // 方式一
        System.out.println(str1.equals("hello"));
        //方式二
        System.out.println("hello".equals(str1));

在上述方式中,常选择方式二

若str1为null,代码就会抛出异常,而方式二不会。

三、字符串常量池

常量:和变量相比,“hello”这就是常量(字符串的字面值常量)

池:计算机中一个重要术语   内存池、线程池、进程池、数据库连接池、对象池

池的目的就是为了降低开销,提高效率,本质是把频繁使用的东西提前保存好,以备用到的时候,随时就能用。

Java会把一些字符串常量放到内置的“字符串常量池”中。

String str1 = "hello" ;
String str2 = "hello" ;
String str3 = "hello" ;
System.out.println(str1 == str2); // true
System.out.println(str1 == str3); // true
System.out.println(str2 == str3); // true

内存布局如下:

在这里插入图片描述

 以上代码并没有开辟新的堆内存空间

原因在于String类的设计采用了共享设计模式

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

1.如果现在采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中;

2.如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如果有指定内容,将直接进行引用;

3.如果没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用。

类对象在实例化时常采用构造方法实例化

面试题:

        String str1 = new String("hello");
        String str2 = "hello";
        System.out.println(str1==str2);
        // 采用String构造方法直接实例化
        //输出结果为false
        String str3 = new String("hello").intern();
        //直接使用String str3 = "hello";直接赋值也可
        String str4 = "hello";
        System.out.println(str3==str4);
        //采用intern方法手动将hello放入字符串常量池中
        //输出结果为true

两种方法的区别:

(1)构造方法:

缺点一:在new String执行完之后,发现并没有引用指向0x100(举个例子)这个对象,于是该对象就会被JVM垃圾回收站给回收掉;

缺点二:字符串共享问题,同一个字符串可能会被存储多次,比较浪费空间。

直接采用String构造方法就会开辟两块堆内存空间,不会自动保存在对象池中,可以使用intern()方法手动入池。(拿着当前这个字符串里的内容在字符串常量池中找,直接返回该池中的地址,若不存在,则把当前字符串的内容加到常量池中,返回池中地址)

 (2)直接赋值

只会开辟一块堆内存空间,并且该字符串对象可以自动保存在对象池中以供下次使用。

四、Java中为何要设计成字符串不可变

 1.方便放入池中,如果是可变的对象,一旦池中的内容发生改变,就会影响到所有引用这个池对象的结果;

2.对象内容不可变,则对象的hashCode(简单粗暴的理解成对象的“签名”用来识别对象身份的方式)也不可变,方便和hash表这样的结构配合使用。

3.对象不可变,线程安全更有保证

String s = "hello"; 即将其变为“hella”此种操作,在Java中,只能通过构造一个新的对象来完成。

关于反射:

• 反射是面向对象编程的一种重要特性, 有些编程语言也称为 “自省”.
• 指的是程序运行过程中, 获取/修改某个对象的详细信息(类型信息, 属性信息等), 相当于让一个对象更好的 “认清自己” .
• Java 中使用反射比较麻烦一些. 我们后面的课程中会详细介绍反射的具体用法。

五、字符、字节、字符串

1. 字符与字符串

 2. 字节与字符串

字节常用于数据传输以及编码转换的处理之中,String 也能方便的和 byte[] 相互转换。

在这里插入图片描述

3. 小结

何时使用byte[],何时使用char[]呢?

(1)byte[]是把String按照一个字节一个字节的方式处理,这种适合在网络传输,数据存储这样的场景下使用,更适合针对二进制数据来操作;

(2)char[]是把String按照一个字符一个字符的方式处理,更适合针对文本数据来操作,尤其是包含中文的时候。

六、字符串常见操作

1. 字符串比较

 在这里插入图片描述

2.字符串查找

 在这里插入图片描述

 在使用indexOf()需要注意的是,如果内容重复,它只能返回查找的第一个位置

        String str = "helloworld";
        System.out.println(str.indexOf("l"));//2
        System.out.println(str.indexOf("l",5));//8
        System.out.println(str.lastIndexOf("l"));//8

3. 字符串替换

在这里插入图片描述

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

字符串拆分

 在这里插入图片描述

 注意:

拆分是特别常用的操作. 一定要重点掌握. 另外有些特殊字符作为分割符可能无法正确切分, 需要加上转义。
• 字符"|","*","+“都得加上转义字符,前面加上”".
• 而如果是"",那么就得写成"\".
• 如果一个字符串中有多个分隔符,可以用"|"作为连字符

5.字符串截取

在这里插入图片描述

 注意:

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

6. 其他

在这里插入图片描述

七、StringBuffer和StringBulider

String是不可变对象,不能直接修改内容,如果我们需要使用可变版本的String,就需使用StringBuffer和StringBulider,两个类的用法基本一摸一样

StringBuffer类的一些方法:

在这里插入图片描述

注意:

String 和 StringBuffer 类不能直接转换,想互相转换可以采用如下原则:
• String 变为 StringBuffer:利用StringBuffer的构造方法或append()方法;
• StringBuffer 变为 String:调用toString()方法。

经典面试题:String、StringBuffer、StringBuilder的区别:

• String 的内容 不可修改 , StringBuffer 与 StringBuilder 的内容 可以修改 ;
• StringBuffer 与 StringBuilder 大部分功能是 相似的 ;
• StringBuffer采用同步处理,属于线程安全操作 ;而 StringBuilder未采用同步处理,属于线程不安全操作(核心区别)
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值