【java】认识String、StringBuffer及StringBuilder

1、Object

1.1 概念

Object类是所有Java类的祖先,也就是说我们所说的”顶级父类”
它存在于java.lang.Object,这个包不需要我们手动导包
需要注意的是:每个类都使用Object作为超类.所有对象(包括数组)都实现这个类的方法.
在不明确给出超类的情况下,Java会自动把Object类作为要定义类的超类。

 1.2 常用方法介绍

toString()  ——  本方法用于返回对应对象的字符串表示。

hashCode()  ——  本方法用于返回对应对象的哈希码值
小贴士:哈希码值的得出是通过一种算法,意在让不同的对象具有不同的哈希码值,用于区分不同的对象.但是有时候也存在不同对象哈希码值相同的特殊情况,我们称之为”哈希碰撞”现象

equals()  ——  本方法用于指示其他某个对象是否与当前对象”相等”。

2、String

2.1 特点

String是一个封装char[]数组的对象,字符串不可变

对于Java中的字符串类String而言,字符串的不可变性是通过使用final修饰类和私有化内部字符数组实现的。因此,可以说既是final的原因,也是private的原因。

  1. final修饰类String类被声明为final,意味着它不能被继承。这样做的原因是为了防止对字符串类进行子类化,因为字符串的不可变性是字符串类设计的核心特性之一。通过将String类声明为final,可以确保不会有子类修改和破坏字符串的不可变性。

  2. 私有化内部字符数组String类内部使用一个私有的char数组来存储字符串的字符序列,并将其声明为final私有化数组意味着其他类无法直接访问和修改该数组,从而保护字符串的内容不被外部代码修改。

  3. 一定要注意value是一个final类型,不可以修改:即value不能指向新的地址,但是单个字符内容是可以变化的。

 2.2 创建String对象的方式

方式一:通过字面量定义的方式

1. String s1="hsp"

2. 通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池中

3. 再次使用相同的内容时,会直接访问堆中常量池中存在的对象。

String s1="hsp";
String s2="hsp";
System.out.println(s1==s2);//true

方式二:通过new + 构造器() 的方式

1. String s3 = new String("hsp")

2. 首先,字符串常量池会检查是否存在值为"hsp"的字符串对象。如果字符串常量池中不存在该对象,它将在常量池中创建一个新的字符串对象。无论字符串常量池中是否存在值为"hsp"的字符串对象,使用new关键字和构造器调用String类的构造器会在堆内存中创建一个新的字符串对象。这个对象将拥有与常量池中的对象相同的内容,但是它们是两个不同的对象,分别在不同的内存位置上。

结论

  1. 常量与常量的拼接结果在常量池,且常量池中不会存在相同内容的常量
  2. 只要其中有一个结果是变量,结果就在堆中
  3. 如果拼接的结果调用intern()方法,返回值就在常量池中
public class StringExercise04 {
    public static void main(String[] args) {
        Person p1 = new Person();
        p1.name = "lyedu";
        Person p2 = new Person();
        p2.name = "lyedu";

        System.out.println(p1.name.equals(p2.name)); //比较的内容 true
        System.out.println(p1.name == p2.name); //true
        //"lyedu"返回的地址:就是在常量池中的地址
        //p1.name 指向的也是常量池中的"lyedu" 对应的地址
        System.out.println(p1.name == "lyedu"); //true

        String s1 = new String("bcde");
        String s2 = new String("bcde");
        System.out.println(s1 == s2); //false
    }
}

class Person {
    public String name;
}

3、面试题

题1:String a = "hello" + "abc"  创建了几个对象?

1个,常量与常量的拼接结果在常量池,且常量池中不会存在相同内容的常量。常量相加,看的是池。

题2:String a = "hello";  String b = "abc"; String c = a + b;创建了几个对象?画出内存图?

解析:在不考虑常量池中存在的情况下,创建了4个对象。变量相加,是在堆中。

public class StringExercise05 {
    public static void main(String[] args) {
        String a = "hello"; //创建a对象    1
        String b = "abc"; //创建b对象      2
        //解读
        //1.先创建一个StringBuilder sb = new StringBuilder();  3
        //2.执行 sb.append("hello");
        //3.执行sb.append("abc");
        //4.String ret = sb.toString();    4
        //最后其实是 c 指向堆中对象的(String) value[]->池中 "helloabc"
        String c = a + b;  
        String d = "helloabc";
        System.out.println(c == d); //false

        String e = "hello" + "abc";
        System.out.println(d == e);//true
    }
}

题3:

public class StringExercise06 {
    public static void main(String[] args) {
        String s1 = "lyedu";//指向常量池中的"lyedu"
        String s2 = "java";//指向常量池中的"java"
        String s5 = "lyedujava"; //指向常量池中的"lyedujava"
        String s6 = (s1 + s2).intern(); //指向池中的 "lyedujava"
        System.out.println(s5 == s6); //true
        System.out.println(s5.equals(s6)); //true
    }
}

题4:

public class StringExercise07 {
    public static void main(String[] args) {
        Test1 ex = new Test1();
        ex.change(ex.str, ex.ch);
        System.out.println(ex.str + " and ");
        System.out.println(ex.ch);
    }
}

class Test1 {
    String str = new String("ly");
    final char[] ch = {'j', 'a', 'v', 'a'};

    public void change(String str, char ch[]) {
        str = "java";
        ch[0] = 'h';
    }
}

输出结果为:

ly and 
hava

题5:String str = new String(“a”) + new String(“b”),创建多少个对象

解析:

对象1:new StringBuilder()

对象2:new String("a")

对象3:常量池中的"a"

对象4:new String("b")

对象5:常量池中的"b"

深入剖析:StringBuilder中的toString():

对象6:new String("ab")

强调一下,toString()的调用,在字符串常量池中,没有生成"ab"。只有在直接使用字符串字面量(如"abc")进行赋值或声明时,才会将字符串对象存储在字符串常量池中。对于动态生成的字符串,如拼接操作的结果,会在堆中创建新的对象。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值