11.String

String的intern()方法

intern方法用来返回常量池中的某字符串,如果常量池中已经存在该字符串,则直接返回常量池中该对象的引用。否则,在常量池中加入该对象,然后返回引用。

intern()判断这个常量是否存在于常量池。
  (1)如果存在
   1.1判断存在内容是引用还是常量,
    如果是引用,
     返回引用地址指向堆空间对象,
    如果是常量,
     直接返回常量池常量
  (2)如果不存在
  2.1将当前对象引用复制到常量池,并且返回的是当前对象的引用

    String a1 = "AA";
    System.out.println(a1 == a1.intern()); //true
    String a2 = new String("B") + new String("B");  //a2 堆中
    a2.intern();// 把堆中a2的地址放入常量池
    String a3 = new String("B") + new String("B"); //a3 堆中
    System.out.println(a2 == a3.intern());//true
    System.out.println(a3 == a3.intern());//false
    String a4 = new String("C") + new String("C");// a4堆中
    System.out.println(a4 == a4.intern()); //true

intern()方法总结

1.只在常量池上创建常量
    String a1 = "AA";
2.只在堆上创建对象
    String a2 = new String("A") + new String("A");
3.在堆上创建对象,在常量池上创建常量
    String a3 = new String("AA");
4.在堆上创建对象,在常量池上创建引用
    String a4 = new String("A") + new String("A");//只在堆上创建对象AA
    a4.intern();//将该对象AA的引用保存到常量池上
5.在堆上创建对象,在常量池上创建引用,不会在常量池中再创建常量。
    String a5 = new String("A") + new String("A");//只在堆上创建对象
    a5.intern();//在常量池上创建引用
    String a6 = "AA";//此时不会再在常量池上创建常量AA,而是将a5的引用返回给a6
    System.out.println(a5 == a6); //true
6.有某些特殊的字符串默认加载入常量池,如java
两个例题及其内存分析图


在这里插入图片描述

String

String对象一经创建则不可改变。

对象不可改变,但这并不表示引用不可以改变
对象不可改变,但这并不表示引用不可以改变
对象不可改变,但这并不表示引用不可以改变

可以更加深入理解String的代码

        String s1="zhangsan";//存储常量池中
        String s2="zhangsan";
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s1==s2);//true

        System.out.println("-----------------------");

        String s3=new String("zhangsan");
        String s4=new String("zhangsan"); 
        System.out.println(s3==s4);     //false
        System.out.println("----------修改value[]----------");
        //获取String的类对象
        Class<? extends String> class1 = s1.getClass();
        //获取String value属性
        Field field=class1.getDeclaredField("value");
        //设置访问权限
        field.setAccessible(true);
        //获取value的值
        char[] v= (char[]) field.get(s1);
        System.out.println("v的长度"+v.length);
        v[0]='x';

        System.out.println(s2);
        System.out.println(s3);
        System.out.println(s4);

最后输出的s2,s3,s4都已经改变了,说明三个引用都是指向了同一个String。这是因为常量池里面已经有了zhangsan这个字符串,所以不会再创建新的字符串。内存图如下:

这里的String s3 = new String(“zhangsan”); 实际上只是创建了一个引用,这个引用是指向常量池里面的String。

在String变量(进行相加的时候,实际上是创建了一个StringBuilder的对象来进行字符串的连接最后返回一个字符串,并不是原来的字符串进行连接,字符串是不可变的。源代码与反编译代码如下:

    String s = "hey";
    String s1 = "damon";
    String s3 = s + s1;
		String s = "hey";
		String s1 = "damon";
		String s3 = (new StringBuilder()).append(s).append(s1).toString();

也只是String变量相加的时候,如果是两个字面量相加,那么会直接加载入方法区,并且仅在内存中生成一个对象。如String str = “hello” + “damon”)

一个关于String对象创建的例题:
```java
String str = "";
for(int i = 0; i < 5000; i++){
    str = str + i;
}

这道题相当于产生了10k个对象,因为字符串是不可变的,并且在进行字符串的拼接时,i也被创建为一个对象。这种做法非常消耗时间和空间。

StringBuider和StringBuffer
  • 它们与String的核心区别:
    String:private final char value[];
    StringBuider和StringBuffer的父类AbstractStringBuilder:char[] value;
    因为String是不可变的,所以对String进行修改过后它的hash值会更改,但是更改过后StringBuilder和StringBuffer却不会发生改变,说明StringBuilder和StringBuffer是可更改的字符串。
  • StringBuilder是线程不安全的,效率高,一般来说是用他
  • StringBuffer线程安全,效率低。
StringBuider和StringBuffer的常用方法:

常用的成员方法

​ 2.2.1 追加:append()

		/*
		StringBuffer append(String str) 
        StringBuffer insert(int offset, String str)  
		*/
        StringBuffer sb1 = new StringBuffer();
        StringBuffer sb2 = new StringBuffer();
        sb1.append("hello");
        sb2.append("hello");
        System.out.println(sb1 == sb2);//输出结果是false,因为每一个StringBuffer都是一个独立的字符数组

		//方法链
		sb1.append("java").append("java").append("java").append("java");

		//插入
		sb1.insert(2,"hhhhhhhh");
		System.out.println(sb1);//从0开始计数

​ 2.2.2 删除

		/*
		 StringBuffer delete(int start, int end) 
		StringBuffer deleteCharAt(int index) 
		*/

		//删除指定区间的字符串
		sb1.delete(2,3);//同样是含头不含尾

		//删除指定位置上的字符
		sb1.deleteCharAt(0);
		System.out.println(sb1);

​ 2.2.3 替换

		/*
		 StringBuffer replace(int start, int end, String str) 
		 void setCharAt(int index, char ch) 

​ 2.2.4 获取

		//和String类中的用法相同
		/*
		indexOf
		lastIndexOf
		charAt
		length
		substring
		*/

​ 2.2.5 反转

		// StringBuffer reverse() 
		StringBuffer sb3 = new StringBuffer("my name is zhansan");
		sb3.reverse();
		System.out.println(sb3);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值