java中三大特殊类之—String类

目录

概念

1.创建字符串的三种方式

2.字符串的内存布局

3.字符串相等时的比较

1)比较方法:equals

2)用户输入与字符串字面量比较

3)字符串常量池 

4.小结

5.理解字符串的不可变性⭐

a. 为何字符串对象内容无法修改?

b.修改字符串

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

StringBuffer:线程安全

StringBulider:线程不安全

6.StringBuilder

1)String->StringBuilder

2)StringBuilder—>String

正确写法:⭐⭐

3)StringBuilder具备一些String不具备的方法

7.String<->char[]的相互转换

8.String<->byte

 什么时候用char什么时候用byte?

9.其他常用操作

1)字符串比较

2)字符串查找

3)字符串替换

注意:⭐String类的所有修改操作的内部都是创建一个新的字符串,字符串的不可变性要牢记!!!无法修改原字符串!!!

4)字符串拆分

5)字符串截取

6)其他


上一篇:面向对象编程之—抽象类和接口_林纾y的博客-CSDN博客

概念

三大特殊的类:String类,Object类,包装类(这三个都是经过特殊处理的类)

        String类是final修饰的类,不能有子类,为了所有使用JDK的程序员,用的都是一个相同的String类。

1.创建字符串的三种方式

1)直接赋值[推荐]

String str="hello world";

所谓直接赋值,就是采用字面量来赋值。

字面量:直接写出来的值。如10--整型字面量--默认是int;11.2--浮点型字面量--默认是double;""--字符串字面量--默认是String类型。

2)通过new创建String对象

String str=new String("hello world");

 3)通过char数组来创建字符串

char[] data={'h','e','l','l','o'};
String str=new String(data);

2.字符串的内存布局

字符串是一个引用数据类型,引用数据类型的默认值是null且在堆上存储

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

        str,str1叫做字符串类型的引用,在栈上保存 。“world”是字符串的字面量,String的对象,在堆上存储。

3.字符串相等时的比较

1)比较方法:equals

        字符串相等时,使用equals方法比较,不能直接==比较,==比较的是地址,equals比较的是内容。

1)对于基本数据类型,==比较的就是两个变量的值,int a=10;a变量保存的值就是10这个值,int b=100;b保存的值就是100这个值,a==b;所以比较相等时当然比较的是值。

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

3)str1.compareTo(str2)?:这个主要是用来比大小的,返回值是一个整型。Java中,每个类都有equals方法,它是Object类自带方法,在java中,默认所有类都继承了Object类,所以每个类都有equals方法,它的返回值是个boolean值。

4)eg:

右边比较的是对象的地址,想看内容相等,需要equals方法。

左边true是因为字符串的常量池,稍后讨论

String str=new String("HELLO");
String str1=new String("HELLO");
System.out.println(str==str1);//false
System.out.println(str.equals(str1));//true

2)用户输入与字符串字面量比较

eg:假设现在str是由用户输入的,要判断str内容是否是“hello”有几种写法?【字符串与指定值比较时,对于写法的判断?】⭐ 

str.equals("hello");//1❌不推荐--空指针异常

"hello".equals(str);//2✔✔推荐

分析:equals方法是通过对象调用的,说明这是一个成员方法(必须有对象才能使用【所有成员方法,成员变量必须防范空指针异常】)

//1

 //2:"hello"--字符串字面量--字符串的匿名对象,一定非空

3)字符串常量池 

1)JVM会对字符串创建一个字符串的常量池:当使用直接赋值创建字符串时,字面量是第一次出现,JVM就会创建一个String对象并且扔入常量池中,当字面量第二次出现或者多次引用时,并不会创建新的对象,而是复用已有对象。

2)为什么JVM会维护一个常量池:高效

3)池:复用已有对象,保证效率。内存池,线程池,连接池等等,都是池的概念。

4)手工入池

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

String str1=new String("hello").intern();//此时str一共创建了几个对象?:2

分析:程序从右向左执行,"hello"是字符串字面量,第一次出现,在堆上创建了"hello"的对象,这是第一次创建。有new就有新空间,此时在堆上创建了一个新的String对象,将值拷贝为hello。注意此时,创建的变量并未入池,只有直接赋值法创建变量才会入池,"hello"匿名对象在的空间成为垃圾空间。

4.小结

1.使用String创建对象就使用直接赋值法

2.比较内容是否相等调用equals方法

3.字符串的不可变性:字符串本身不可变,内容不可修改,变的只是引用的指向。若要达到修改目的,只能通过反射破坏封装。

5.理解字符串的不可变性⭐

内部存储数据的value数组对外不可见,外部无法直接使用,无法修改内容

问题:输出是world,已经变了,所以什么是不可变性??

分析: 此处只是str指向发生变化,指向了新的字符串对象"world",而对原字符串"hello"没有任何影响。

字符串本身不可变,变的只是引用的指向【数组abc本身内容变了】 

a. 为何字符串对象内容无法修改?

String对象内容实际上存储在内部value[]中,value[]是一个private+final修饰的私有属性,private说明value[]出了String类不可见,无法识别【String类没有提供getter方法,外部无法使用value数组】,final保证了value指向的地址不变。

b.修改字符串

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

import java.lang.reflect.Field;

public class StringCode {
    public static void main(String[] args) throws Exception {
        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);
    }
}

 (课件上的substring是创建了一个新变量,并不是修改原来字符串对象肚子里的内容)

 由于字符串的不可变,若需要修改大量字符串时,我们使用两个sb类替换:

StringBuffer:线程安全

StringBulider:线程不安全

这两个sb类和String类完全无关,是两种不同的类型,不能混为一谈

6.StringBuilder

1)String->StringBuilder

1)直接调用StringBuilder的append方法

2)构造方法传入String对象

2)StringBuilder—>String

调用StringBuilder得toString方法

eg:

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

问:234行代码产生了多少个对象?

分析:

“hello”一个,+=是str+world,先产生“world”对象,然后拼接“helloworld”-3个,继续+=,先“!!!”是一个对象-4个,再“helloworld!!!”-5个,所以理论上产生5个,但是JVM没那么笨,当发现有字符串拼接时,JVM会将字符串转为StringBuilder类【不推荐这么拼接,拼接就直接使用两个SB类】

正确写法:⭐⭐

//        String->StringBuilder
//        通过构造方法将String类型转化为StringBuilder类型
        StringBuilder sb=new StringBuilder("hello");
//        调用append方法将字符串变为StringBuilder
        sb.append("world");//⭐StringBuilder通过append方法扩展拼接内容
        sb.append("!!!");
//        此时StringBuilder内部储存的就是helloworld!!!
//        将StringBuilder还原为String:StringBuilder->String
        String ret=sb.toString();
        System.out.println(ret);

3)StringBuilder具备一些String不具备的方法

为何不具备:本质是StringBuilder内容可改,而String内容无法修改

1)reverse:反转(即字符串反转)

sb.reverse();

2)delete(int start,int end):删除指定范围内的字符串内容

sb.delete(5,10);//左闭右开区间

Java中牵扯到区间的取值一般来说都是左闭右开区间:[start,end)

 3)insert(int start,插入的数据):插入字符串

7.String<->char[]的相互转换

1)String->char[]

String的toCharArray()方法

String str="hello";
//str->字符数组
char[] data=str.toCharArray();
System.out.println(Arrays.toString(data));

2)取得String某一个具体的字符:String->char

String的charAt()方法

//取出字符串中每个字符
for (int i = 0; i < str.length(); i++) {
    char c=str.charAt(i);//取出字符串中某个字符
    System.out.print(c+"、");

eg:判断用户输入的字符串是否由纯数字组成—逐个取出判断

public static boolean isNumStr(String str){
    for (int i = 0; i < str.length(); i++) {
        char c=str.charAt(i);
        if(c<'0'||c>'9') {
            return false;
        }
    }
        return true;
}

 3)char[]->String

  public static void main(String[] args) {
        char[] data={'h','e','l','l','o'};
        String str=new String(data);
        String str1=new String(data,0,3);//左闭右开
        System.out.println(str);
        System.out.println(str1);
    }

8.String<->byte

1)String->byte[]【只能转化为byte[]数组,不能是单独byte】

String str="美女";
//未指定编码就是当前操作系统的默认编码
byte[] data=str.getBytes();
//指定UTF_8编码
byte[] data1=str.getBytes(StandardCharsets.US_ASCII);
System.out.println(Arrays.toString(data));
System.out.println(Arrays.toString(data1));

2)byte[]->String

 什么时候用char什么时候用byte?

byte一般用在网络传输或者输入输出中(读写文件)使用。判断网速的默认单位就是byte;如果处理的是文本(或者说字符串的内容)用char。

9.其他常用操作

1)字符串比较

String str="hello";
String str1="HELLO";
System.out.println(str.equals(str1));
System.out.println(str.equalsIgnoreCase(str1));
System.out.println(str.compareTo(str1));

2)字符串查找

 ⭐⭐查找子串是否存在:contains()

System.out.println(str.contains("ell"));//true
System.out.println(str.contains("cdbo"));//false

3)字符串替换

注意:⭐String类的所有修改操作的内部都是创建一个新的字符串,字符串的不可变性要牢记!!!无法修改原字符串!!!

 

4)字符串拆分

注意:按照特殊字符拆分需要转义处理【eg拆字符串152.25.1,点操作符是属于java中特殊操作符(访问操作符),需要转义\\.

5)字符串截取

String str="helloworld";
System.out.println(str.substring(5));//world
System.out.println(str.substring(5,9));//worl

6)其他

下一篇:java中三大特殊类之—Object类和包装类_林纾y的博客-CSDN博客

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值