String

底层实现

//String的底层:
private final char[] value;

String 对象的字符内容是存储在一个字符数组中的
说明:
i)private 意味着外面无法直接获取字符数组。
ii)final 意味着字符数组的引用不可改变。表示String类不可被继承。
iii)通过让 value 指向新的数组对象来实现修改 String对象,因此字符串的字符数组内容也不可变。

不可变性

String的不可变性体现:
i)当对字符串重新赋值时,需要重新指定内存区域赋值,不能已使用原有的value进行赋值。
ii)当对现有的字符串进行拼接操作时,也要重新指定内存区域赋值,不能使用原有的value进行赋值。
iii)当调用String的replace()方法修改指定字符或字符串时,也需要指定内存区域赋值,不能使用原有的value进行赋值。

String的实例化方式

方式一:字面量方式

通过字面量定义的方式(区别new)给一个字符串赋值,此时的字符串值声明在字符串常量池中
字符串常量池是不会存储相同内容的字符串的。

//String是引用数据类型
//通过字面量定义的方式:此时的s1和s2的数据javaEE声明在方法区中的字符串常量池中。常量池中只有一个javaEE,所以s1和s2指向同一个地址。
String s1 = "javaEE";
String s2 = "javaEE";

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

方式二:new + 构造器

通过new + 构造器的方式,数据是在堆空间中开辟空间以后对应的地址值。地址值对应的内容还是在字符串常量池中。

//通过new + 构造器的方式:此时的s3和s4保存的地址值,数据是在堆空间中开辟空间以后对应的地址值。地址值对应的内容还是在字符串常量池中。
String s3 = new String("javaEE");
String s4 = new String("javaEE");

System.out.println(s1 == s3);//false
System.out.println(s1 == s4);//false
System.out.println(s3 == s4);//false

注意:
字面量是在字符串常量池中,new的是在堆空间中。

String的拼接

结论:
i)常量与常量的拼接结果在常量池,且常量池中不会存在相同内容的常量。
ii)只要其中有一个变量,结果就在堆中。
iii)如果拼接的结果调用intern()方法,返回值就在常量池中。

@Test
    public void test3(){
        String s1 = "javaEE";
        String s2 = "hadoop";

        String s3 = "javaEEhadoop";//s3和s4都是在常量池中,拼接的这种就是同一个
        String s4 = "javaEE" + "hadoop";
        String s5 = s1 + "hadoop";//这里s5就相当于new了,因为出现了变量s1
        String s6 = "javaEE" + s2;
        String s7 = s1 + s2;
        System.out.println(s3 == s4);//true
        System.out.println(s3 == s5);//false
        System.out.println(s3 == s6);//false
        System.out.println(s3 == s7);//false
        System.out.println(s5 == s6);//false
        System.out.println(s5 == s7);//false
        System.out.println(s6 == s7);//false

        String s8 = s5.intern();//返回值得到的s8使用的常量池中已经存在的“javaEEhadoop”
        System.out.println(s3 == s8);//true

    }

面试题

面试题一

String s = new String(“abc”);方式创建对象,在内存中创建了几个对象?
两个一个是堆空间中new结构另一个是char[]对应的常量池中的数据:“abc”
常量池中不会出现两个相同的abc,若有现成的直接用现成的。否则,创建新的。
不能使用s.属性改变abc的值,只能在常量池中新建一个。

面试题二

public class StringTest {
    String str = new String("good");
    char[] ch = {'t', 'e', 's', 't'};

    public void change(String str, char ch[]) {
        str = "test ok";
        ch[0] = 'b';
    }

    public static void main(String[] args) {
        StringTest ex = new StringTest();
        ex.change(ex.str, ex.ch);//String不可变性
        System.out.println(ex.str);//good
        System.out.println(ex.ch);//best
    }
}

原理:java值传递机制与String不可变性

Java里方法的参数传递方式只有一种:值传递。 即将实际参数值的副本(复制品)传入方法内,而参数本身不受影响。

  1. 形参是基本数据类型:将实参基本数据类型变量的“数据值”传递给形参
  2. 形参是引用数据类型:将实参引用数据类型变量的“地址值”传递给形参

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值