数据的三种存放方式
1. 直接存放入常量池
String s = "123" ;
2.直接存入常量池 ,并在堆中创建存储空间
String s = new String("123") ;
3.123,456直接放进常量池,当调用String.intern方法时,字符串123456才进入常量池,否则123456永远不进入常量池。
String str = new StringBulider("123").append("456").toString();
String.intern方法是一个Native方法,作用是:如果常量池中已经存在此String对象的字符串,则返回此对象在常量池中的地址值;否则,将此字符串的地址值添加到常量池中,并返回此地址值(jdk1.7以后的)。
字符类型的 == 关系
例题2
String s1 = "abcd" ;
String s2 = "abcd" ;
String s3 = "ab"+ "cd" ;
String s4 = new String("abcd") ;
String s5 = "ab" + new String("cd") ;
System.out.println( s1 == s2 ) ;
System.out.println( s2 == s3 ) ;
System.out.println( s2 == s4 ) ;
System.out.println( s2 == s5 ) ;
System.out.println( s4 == s5 ) ;
结果为:
true s1==s2 无争议
true s2==s3 因为s3由字符类型构成 字符类型相同 所以相等
false 用new String() 创建的字符串不是常量,new String() 创建的字符串不放入常量池中,它们有自己的地址空间
false 因为有后半部分 new String(”cd”) new String() 创建的字符串不放入常量池中
false 因为有后半部分 new String(”cd”) new String() 创建的字符串不放入常量池中
特殊存在时候的 == 关系
String a = "a1" ;
String b = "a" + 1 ;
System.out.println(( a == b )) ;
String a = "ab" ;
String bb = "b" ;
String c = "a" + bb ;
System.out.println(( a == b )) ;
String a = "ab" ;
final String bb = "b" ;
String b = "a" + bb ;
System.out.println(( a == b )) ;
结果是:
true 字符串常量的"+“号连接
false 在字符串的"+“连接中,有字符串引用存在,而引用的值在程序编译期是无法确定的 ,只有在程序运行期来动态分配并将连接后的新地址赋给b
ture bb字符串加了final修饰,对于final修饰的变量,,它在编译时被解析为常量值的一个本地拷贝存储到自己的常量池中或嵌入到它的字节码流中。所以此时的"a" + bb和"a" + "b"效果是一样的。
final StringBuffer a = new StringBuffer("111");
final StringBuffer b = new StringBuffer("222");
a=b;//此句编译不通过
final StringBuffer a = new StringBuffer("111");
a.append("222");// 编译通过
final只对引用的"值"(即内存地址)有效,它迫使引用只能指向初始指向的那个对象,改变它的指向会导致编译期错误。至于它所指向的对象 的变化,final是不负责的。
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\t" + (i1 == i2));
System.out.println("i1=i2+i3\t" + (i1 == i2 + i3));
System.out.println("i4=i5\t" + (i4 == i5));
System.out.println("i4=i5+i6\t" + (i4 == i5 + i6));
System.out.println();
结果为 :
true Integer i1=40;Java在编译的时候会执行将代码封装成Integer i1=Integer.valueOf(40);通过查看Source Code发现
true
false
ture 进行了重写实现加减
String s1 = "abc";
String s2 = "abc";
System.out.println(s1.equals(s2));
System.out.println(s1 == s2);
为什么第二个会是true呢?
这就涉及到了内存中的常量池,常量池属于方法区的一部分,当运行到s1创建对象时,如果常量池中没有,就在常量池中创建一个对象"abc",第二次创建的时候,就直接使用,所以两次创建的对象其实是同一个对象,它们的地址值相等。