目录

连接符"+"

1.关于String的immutable性质。

另外补充一点intern()

包装类的常量池技术


连接符"+"

String a="a";String b="b";

String s="a"+"b"; sysytem.out.println(s=="ab")

//返回true。

//分析:JVM对于字符串常量”+“号连接,在程序编译器,JVM就将字符串常量的”+“连接优化为连接后的值,即如上s经编译器优化

//后在class中已经是"ab",即可在编译后字符串s的值已经确定下来,所以返回true。

String s=a+"b"; system.out.println(s=="ab");//返回false

/* JVM对于字符串引用进行“+”连接时是无法被编译优化成字符串常量在赋给s的,只有在程序运行期进行动态分配并将连接后的新地址赋给s。  */

将 String a 改为 final String a="a"后,system.out.println(s="ab");//返回true

//分析:对于final修饰的变量,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量 池中或嵌入到它的字节码流中。所以 //此时的a + ”b“和"a" + "b"效果是一样的。故上面程序的结果为true。

关于”+“连接符效率低下的原因:

首先先了解有字符串引用时连接的内部原理。

String a="a";

String b="b";

String s=a+"b";

会被编译为:

s=new StringBuffer().append(a).append("b").toString();

在应用到循环中时

for(int i=1;i<100;i++) s+="a";

每做一次循环就会进行一次StringBuffer的创建与销毁。

解决方案:在循环外创建一个StringBuffer进行循环后在复制给s。可以省去n-1次创建和销毁对象的时间

速度差异:

java stream 链接成字符村_java stream 链接成字符村

1.关于String的immutable性质。

1.关于String的immutable性质。

由于String的实例一旦生成就不会在改变,所以会导致存在多个临时变量在常量池中 如s=”a"+"b" 则 a,b,ab都在常量池中,而StringBuffer时可变的,所以建议使用String buffer。

2.String中的final的用法与理解

final StringBuffer a=new StringBuffer("a");

final StringBuffer b = new StringBuffer("b");

a=b;//无法通过编译

a.append(b);//编译通过

由此可见final针对的是引用的值即内存地址,他迫使引用指向初始的对象,改变它的指向会报错,而它指向的对象发生变化,final是不负责的。

另外补充一点intern()

//    String str2="李鑫"; //只要这一句放到intern前就返回false
       String str1 = new String("李") + new String("鑫");
        //System.out.println(str1.intern() == str1); 先进行intern则全返回true
       System.out.println(str1 == "李鑫"); //判断时str1与指向李鑫的引用比较;如果"李鑫"="李鑫" 则不会在常量池中生成相应字符串
        System.out.println(str1.intern() == str1);
        System.out.println(str1.intern() == "李鑫");
        //false ,false,true


//else
public static void main(String[] args) throws Exception {
        String s1= new String("li")+new String("xin");
        String s2 ="lixin";
        s1.intern();
        String s3 ="lixin";
        String s4 ="lixin";
        System.out.println(s1==s2);
        System.out.println(s1==s3);
        System.out.println(s1==s4);
        //all false
    }

大致理解:在1.6(不包含1.6)以后,若使用String.intern()时,该String在常量池不存在,则将这个String对象添加到常量池并返回指向这个String的引用str1。然后在创建一个字符串为该常量值时,会直接指向该引用。所以会相等。

相关源码:意思是常量池存在则直接返回string,不存在则在常量池中引用该String,为什么可以做到呢,因为常量池在jdk1.7以后就搬到了堆中,可以直接引用,而不是生成。

When the intern method is invoked, if the pool already contains a
string equal to this {@code String} object as determined by
the {@link #equals(Object)} method, then the string from the pool is
returned. Otherwise, this {@code String} object is added to the
pool and a reference to this {@code String} object is returned.

具体原因参考博客:  (Intern)

包装类的常量池技术

建议参考:

总结:

  1. 除了两个包装类Long和Double 没有实现这个缓存技术,其它的包装类均实现了它
  2. Integer实现范围只有-128~127
  3. == 这个运算在不出现算数运算符(+,-...)的情况下 不会自动拆箱,所以i1 和 i 2它们不是数值进行的比较,仍然是比较地址是否指向同一块内存

第一点示例:

Integer i1 = 40;
Integer i2 = 40;
Double i3 = 40.0;
Double i4 = 40.0;
System.out.println("i1=i2   " + (i1 == i2));//true
System.out.println("i3=i4   " + (i3 == i4));//false

第2,3点示例

Integer i1 = 40;
  Integer i2 = 40;
  Integer i3 = 0;
  Integer i4 = new Integer(40);
  Integer i5 = new Integer(40);
  Integer i6 = new Integer(0);

  System.out.println("i1=i2   " + (i1 == i2));
  System.out.println("i1=i2+i3   " + (i1 == i2 + i3));
  System.out.println("i1=i4   " + (i1 == i4));
  System.out.println("i4=i5   " + (i4 == i5));
  System.out.println("i4=i5+i6   " + (i4 == i5 + i6));
  System.out.println("40=i5+i6   " + (40 == i5 + i6));

----结果----
(1)i1=i2   true
(2)i1=i2+i3   true
(3)i1=i4   false
(4)i4=i5   false
(5)i4=i5+i6   true
(6)40=i5+i6   true
Integer i1 = 400;
  Integer i2 = 400;
  Integer i3 = 0;
  Integer i4 = new Integer(400);
  Integer i5 = new Integer(400);
  Integer i6 = new Integer(0);
  Integer i7 = 1;
  Integer i8 = 2;
  Integer i9 = 3;

  System.out.println("i1=i2   " + (i1 == i2));
  System.out.println("i1=i2+i3   " + (i1 == i2 + i3));
  System.out.println("i1=i4   " + (i1 == i4));
  System.out.println("i4=i5   " + (i4 == i5));
  System.out.println("i4=i5+i6   " + (i4 == i5 + i6));   
  System.out.println("400=i5+i6   " + (400 == i5 + i6));


----结果----
i1=i2   false
i1=i2+i3   true
i1=i4   false
i4=i5   false
i4=i5+i6   true
400=i5+i6   true