java的String类,自动装箱与拆箱

本文详细解析了Java中String、StringBuffer与StringBuilder类的区别及应用,探讨了字符串拼接的效率问题,并深入介绍了基本数据类型与封装类的区别,包括自动装箱与拆箱的过程,以及Integer与int的比较细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习别人的博客后自己写的笔记,感觉看了她其他博客还是挺有收获的,这是原博客传送门

1.String类,StringBuffer类以及StringBuilder类

首先String类是不可变类,即一旦产生一个String类的对象,便不再允许改变;但是StringBuffer和StringBuilder类是可变类。

StringBuffer和StringBuilder类的原理和操作基本相同,区别在于StringBuffer支持并发操作,线性安全的,适合多线程中使用。StringBuilder不支持并发操作,线性不安全的,不适合多线程中使用,但StringBuilder在单线程中的性能比StringBuffer高。在单线程中应该用StringBuilder代替StringBuffer
原博客传送门

2.字符串拼接

两个字符串的拼接可以直接用“+”来连接

String string1 = "Hello";
String string2 = "World";
String string3 = string1 + string2;

但是使用"+"来进行字符串的拼接效率低下,每次连接字符串都会构建一个新的String对象,既耗时又浪费空间;使用StringBuffer和StringBuilder可以避免这个问题。

StringBuilder stringBuilder = new StringBuilder();

每次需要在末尾添加内容时就调用append方法

stringBuilder.append("Hello");//stringBuilder结果为:Hello
String string = " World";
stringBuilder.append(string);//stringBuilder结果为:Hello World

在需要String对象时,可以使用toString方法得到一个String对象:

String newString = stringBuilder.toString();

StringBuffer用法和StringBuilder类似,不再赘述。

3.StringBuilder的部分API

  • int length()
    返回构建器或缓冲器中的代码单元数量
  • StringBuilder append(String str)
    追加一个字符串并返回this(即返回当前的StringBuilder对象)
  • StringBuilder append(char c)
    追加一个代码单元并返回this(即返回当前的StringBuilder对象)
  • StringBui 1 der appendCodePoint(int cp)
    追加一个代码点,并将其转换为一个或两个代码单元并返回 this。
  • void setCharAt(int i ,char c)
    将第 i 个代码单元设置为 c。
  • StringBui 1 der insert(int offset,String str)
    在 offset 位置插入一个字符串并返回 this。
  • StringBuilder insert(int offset,Char c)
    在 offset 位置插入一个代码单元并返回 this。
  • StringBui 1 der delete(1 nt startindex,int endlndex)
    删除偏移量从 startindex 到 -endlndex-1 的代码单元并返回 this。

4.字符串相等

String类型并不是Java中的基本类型,变量名指向的是对象在内存中的地址,所以不能使用常量的==来比较两个字符串是否相等,它仅仅是比较两个变量指向的地址是否相同。在不同的地址完全可能存在两个String值相同的对象,故而要调用equals方法进行比较。

        String string1 = "a";
        String string2 = "b";
        String string3 = new String("a");
        String string4 = "ab";
        String string5 = new String("ab");
        String string6 = string1 + string2;
        String string7 = "a";

        System.out.println(string1 == string3);//false
        System.out.println(string4 == string5);//false
        System.out.println(string5 == string6);//false
        System.out.println(string4 == string6);//false
        System.out.println(string1 == string7);//true
        string6 = "a";
        System.out.println(string1 == string6);//true

原因分析:
java中有字符串常量池,在采用直接赋值的方式(即String string1 = “a”;)创建一个字符串对象的时候,他会先在字符串常量池中查找是否有这个字符串,如果有,则将新创建的String变量指向该对象地址,如果没有,则在常量池新创建一个字符串,并让String变量指向它,所以直接赋相同值的两个String变量用是“相等的”,这里的相等是指他们指向的对象相同。
但是使用new操作将直接创建一个新的对象,而不管常量池,所以每一个new出来的对象都是不同的,他们的地址自然也不同,所以用“==”比较两个指向new出来的String对象的变量,其结果是false。

equals方法才是用来比较两个字符串字面量是否相等的方法

        //equals方法比较字符串字面量是否相等
        System.out.println(string4.equals(string5));//true

5.Java基本数据类型

在这里插入图片描述

基本数据类型与封装好的类的区别:

  1. 基本类型在传递参数是是按值传递,而封装类型是按引用传递的,即传递的是对象的地址
  2. 默认值不同,int是基本类型,默认值是0,而Integer是对象,对象的默认值为null
  3. 基本类型在内存中是存储在栈中,引用类型的引用(值的地址)存储在栈中,而实际的对象(值)是存在堆中。

Integer与int的区别:

  1. int是一种基本数据类型,而Integer是一种类,是int的包装类
  2. Integer类型的数据必须实例化后才能使用,int不必
  3. 他们的默认值不同
  4. int存储的是值,Integer变量存储的是对象的地址

6.Java的自动拆箱和装箱

讲道理int变量和Integer变量的比较是没有意义的,他们一个是基本数据类型,一个是类的实例;但是又应该可以比较,因为他们实际上都是为了表示一个值;实际上,java是支持这种比较的,在这里面java自动进行了装箱和拆箱的操作

Integer a = 1;//实际上java编译器自动进行了装箱的操作,
			  //等价于Integer a = Integer.valueOf(1);

上面编译器在编译期间自动进行的操作就叫做装箱

Integer a = 1;
int b = a;//这里编译器在编译期间进行拆箱
		  //等价于int b = a.intValue();

这就是java编译器的自动拆箱
由于编译器的自动拆箱与装箱,所以Integer和int类型的变量参与运算是等价的

7.Integer和int的比较

  1. 就像上面说的,new出来的Integer变量实际上是对Integer对象的引用,两个new出来的Integer对象地址不同,所以指向他们的变量是不可能相等的
        Integer b = new Integer(1);
        Integer c = new Integer(1);
        System.out.println(b == c);//false
  1. 一个Integer类型的变量和int类型的变量进行比较时,由于Java的自动拆箱,只要他们表示的值相等就是相等的,等价于两个int类型的变量进行比较
        int a = 1;
        Integer d = 1;
        System.out.println(a == d);//true
  1. 一个new出来的Integer变量与直接赋值产生的变量永远不相等,因为直接赋值的变量指向常量池里面的对象,在栈中,new出来的对象在堆中,他们的比较是对象地址的比较
        Integer b = new Integer(1);
        Integer d = 1;
        System.out.println(b == d);//false
  1. 对于两个非new生成的Integer对象,进行比较时,如果两个变量的值在区间-128到127之间,则比较结果为true,如果两个变量的值不在此区间,则比较结果为false
        Integer d = 1;
        Integer e = 1;
        System.out.println(d == e);//true
        Integer f = 128;
        Integer g = 128;
        System.out.println(f == g);//false

这是因为Integer d = 1;在编译时装箱为Integer d = Integer.valueOf(1);
Integer.valueOf方法的源码如下:

    @HotSpotIntrinsicCandidate
    public static Integer valueOf(int i) {
        if (i >= IntegerCache.low && i <= IntegerCache.high)
            return IntegerCache.cache[i + (-IntegerCache.low)];
        return new Integer(i);
    }

其中IntegerCache.low = -128,IntegerCache.high = 127;
当-128 <= i <= 127时,返回常量池中已有的Integer对象的引用,所以实际上并没有创建新的对象,只不过是把已有对象的地址赋值给变量,所以这时两个变量指向同一个对象,变量值相等。
当i的值不在这个范围内时,返回new的一个对象的地址,这时情况就变成上述1的情况,两个new出来的对象的地址显然不同,故不相等

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值