Java基础-String对象的创建和存储

String对象的特点

String是JDK中内置的一个类:java.lang.string

  • 1.String表示字符串类型,属于引用数据类型,不属于基本数据类型.
  • 2.Java中使用双引号括起来的都是String对象。例如:“abc”、“lei”、“hello world!”,这就是三个对象。
  • 3.Java中规定,双引号括起来的字符串是不可变的,也就是说“abc”从出生到消亡双引号里的内容是不会变的,不可能变成“abcd”,也不可能变成“ab”。
  • 4.字符串都是直接存储在“方法区”的字符串常量池当中的。
  • 5.为什么把字符串存储在“字符串常量池”当中呢。因为字符串在实际开发中使用的很频繁,为了提供效率所以存储在“字符串常量池中”。

String对象创建的两种方式

方式一:通过字符串常量的方式创建

//方式一:通过常量的方式创建string对象
//以下两行代码表示底层创建了3个字符串对象,都在字符串常量池当中。
 String s1 = "abcdef";
 String s2 = "abcdef" + "xy";

方式一 的内存图(截图于老杜JAVA),s1和s2的内存地址指向了字符串常量池中的字符串。因为s2是“abcdef”和“xy”的拼接,又因为“abcdef”,s1已经创建了,所以s2直接拿过来。这也就是为什么要把字符串存储在方法区的字符串常量池中的原因,第一次创建了,第二次使用时就不用创建了直接拿过来用。
在这里插入图片描述

方式二:通过new对象的方式创建

//通过new的方式创建String对象。
//分析:结合以上内容可以先分析s3的“xy”从哪来。
//提示:凡是“”括起来的都在字符串常量池中。
//注意:new对象的时候一定在堆内存中开辟空间。
String s3 = new String("xy");

方式二的内存图,s3在内存中存在的形式就是,栈中的s3的内存地址指向堆中的String对象,堆中的String对象中的内存地址又指向方法区中“xy”的内存地址。
在这里插入图片描述
如果堆里面new的是一个User对象,User对象里有一个String类型的name属性,则User的name里存储的并不是具体的字符串,而是存储的是字符串在字符串常量池中的内存地址。

String对象的“==”和“equals”

思考1,方式一创建的String对象中(s1 == s2)的结果。要知道“==”判断的是内存地址

 public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "hello";
        System.out.println(s1 == s2);
 }

分析,字符串“hello”存储在方法区的字符串常量池中,栈中的s1和s2存储的都是“hello”的内存地址。字符串常量池中有的常量,不会被重复创建。所以s1 == s2为true。
在这里插入图片描述

思考2,方式二 new的String对象中(x == y)的结果。要知道new出来的对象在堆中开辟空间。且“==”判断的是内存地址。

 public static void main(String[] args) { 
        String x = new String("xyz");
        String y = new String("xyz");
        System.out.println(x == y);
 }

分析,既然new出来的对象在堆内存中开辟空间,也就意味着每一个new出来的对象都有一个单独的堆内存地址。虽然堆中的对象都指向的是“xyz”中的字符串常量池中的内存地址,但栈中的x和y都指向x和y在堆内存中的不同的堆内存地址。所以xy为false。
在这里插入图片描述
在这里插入图片描述
于是乎我们得出结论,字符串对象之间的比较不能使用“
”。
"=="不保险,应该调用String对象的equals方法

String对象的比较到底是用“==”还是equals呢?

翻看源码可知Object的equals的方法默认也是使用“==”做比较。
在这里插入图片描述
那咱们再来看看String对象的equals方法(String对象重写了equals方法)
在这里插入图片描述
所以以上案例中x和y的比较应该使用equals。
在这里插入图片描述

"testString"为什么可以通过(.点)调出equals方法

因为“testString”就是一个String字符串对象,只要是对象就能调用方法。

 String k = new String("testString");
 System.out.println("testString".equals(k));
 System.out.println(k.equals("testString"));

在这里插入图片描述

以上两种使用equals方式做比较都可以,但是推荐使用"testString".equals(k)。因为如果k为null的话,k.equals(“testString”)就会报空指针异常。使用为空的对象调用方法就会出错。
在这里插入图片描述

分析以下程序创建了几个对象

/**
 * @author lei
 * @date 2022/4/26 0026 18:35
 * @description 分析以下程序创建了几个对象
 */
public class StringTest03 {
    public static void main(String[] args) {
        /**
         *一共创建了3个对象
         *    方法区字符串常量池中有一个:“hello”
         *    堆内存当中有两个String对象。
         */
        String s1 = new String("hello");
        String s2 = new String("hello");
    }
}

String对象重写了toString方法

在这里插入图片描述
在这里插入图片描述

public class StringTest04 {
    public static void main(String[] args) {
        String s1 = "hello world";
        /**
         * 根据之前所学:输出一个对象的引用的时候,会自动调用Object的toString()方法,
         * 该方法会自动输出对象的内存地址。
         * 但此时我们可以看出s1输出的是“hello world”
         * 结论:String类已经重写了toString()方法。
         */
        System.out.println(s1.toString());

        /**
         * 字符集中,97是a,98是b,99是c
         */
        byte[] bytes = {97,98,99};
        String s2 = new String(bytes);
        System.out.println(s2.toString());
        System.out.println(s2);
    }
}

所以 System.out.println(s2.toString());
System.out.println(s2);输出的是同样的结果。
在这里插入图片描述

string.replaceAll();字符串替换

#replaceAll()的源码
 public String replaceAll(String regex, String replacement) {
        return Pattern.compile(regex).matcher(this).replaceAll(replacement);
    }

在这里插入图片描述

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值