public static void main(String[] args) {
String str = "abc";
str = "bcd";
//String是只读字符串,其引用的字符串内容不可变
//str是一个引用对象,指向字符串对象"abc"
//str = "bcd";是让str重新指向一个新字符串"bcd"对象
//而"abc"对象没有被改变,只是变成一个不可及对象了
//StringBuffer线程安全效率低
//StringBuilder线程不安全效率高
String s1 = "hello";
String s2 = new String("hello");
String s3 = "he";
String s4 = "llo";
String s5 = "he" + "llo";
String s6 = s3 + s4;
String s7 ="java";
String toString = new StringBuilder("tom").append("cat").toString();
String toString2 = new StringBuilder("ja").append("va").toString();
System.out.println(s1.equals(s5));//true
System.out.println(s1 == s5);//true
System.out.println(s1.equals(s6));//true
System.out.println(s1 == s6);//false
System.out.println("------------");
System.out.println(s1.equals(s6.intern()));//true
System.out.println(s1 == s6.intern());//true
System.out.println(s2.equals(s2.intern()));//true
System.out.println(s2 == s2.intern());//false
System.out.println(s1 == s1.intern());//true
System.out.println(s2.intern());
System.out.println(s7 == s7.intern());//true
System.out.println(toString == toString.intern());//true
System.out.println(toString2 == toString2.intern());//false
/* 一:==与equals()与hashCode
<<Effective java>>里面是怎么介绍equals():
自反性:a.equals(b)=true那么b.equals(a)=true
传递性:a.equals(b)=true,b.equals(c)=true那么a.equals(c)=true
对称性:a.equals(b)=true那么b.equals(a)=true
一致性:a.equals(b)=true,当a和b没有被改变时,多次都是true(幂等性)
非null值的引用x,x.equals(null)必须返回false
----------------提高equals的效率-----------------------
1.用==操作符比较"参数是否为这个对象的引用"
2.instanceof操作符检查"参数是否为正确类型"
3.对于类中的管家属性,检查参数传入对象的属性是否与之匹配
4.编写完equals后检查其是否满足对称性,传递性,一致性
5.重写equals总要重写hashCode
6.不用将equals里面的Object对象换为其他类型,重写记得加@Override
----------------equals对hashCode的规定----------------
1.两个对象equasl为true,那么hashCode值一定相同
2.两个对象的hashCode值相同,equasl不一定相同(通话,重地)
以上2点可以不遵守,但是效率会下降(set添加元素时哈希碰撞会造成取的效率低下)
*/
//二+的本质:
//+的本质是: 每次+都创建一个新的StringBuilder进行append(),
//s5,s6都是指向堆中StringBuilder,StringBuilder指向字符串常量池的"hello"
//String的intern()方法返回字符串对象的规范表示。
//如果s.intern() == t.intern()为true 那么s.equals(t)一定为true 。
//得到字符串对象在常量池中对应的版本引用
//如果常量池中有一个字符串与String对象的equals 则返回true
//如果常量池中没有对应的字符串,则该字符串被添加到常量池中,同时返回该字符串的引用
//"123".intern()向字符串常量池中添加"123",返回其引用
//intern()就是看看字符串常量池中有没有这个对象,有就返回没有就创建并返回
//,s2是堆内存中的引用,s2.intern()是字符串常量池里的字符串对象
//,他们地址值不同,==为false
//,他们内容一样,equals()为true
//,s1堆内存中的引用和字符串常量池里的地址值一样,==为true
//,在jdk加载sun.misc.Version这个类的时候有一个初始化的java字符串
//,所以System.out.println(toString2 == toString2.intern());//false
System.out.println("---------+和StringBuffer/StringBuilder的效率-------------------");
//三
/*
什么时候"+"运算符进行字符串连接比调用StringBuffer/StringBuilder
的append()连接字符串效率高?
从结果来看:"+"和StringBuffer/StringBuilder完全等效
因为在java中无论使S用何种方式的字符串连接实际上都是StringBuilder
*/
String s8 = "abc";
String s9 = "ok" + s7 + "xyz" + 5;
System.out.println(s9);
/*
从运行效率和资源消耗来看:
连接字符串表达式简单,"+"和StringBuffer/StringBuilder基本一样(如上)
上面的代码通过反编译后内容:
String s8=(new StringBuilder("ok")).append(s).append("xyz").append(5).toString();
*/
String s10 = "";
Random random = new Random();
for (int i = 0; i < 10; i++) {
s10 = s10 + random.nextInt(1000) + " ";
}
System.out.println(s9);
//上面代码反编译后:
//for(int i = 0; i < 10; i++){
//s9 = (new StringBuilder(String.valueOf(s9)))
// .append(rand.nextInt(1000)).append(" ").toString();}
//创建StringBuilder对象的位置在for内部,每一次循环都会创建一个
//虽然有垃圾回收器,但是工作时间不定,不断的产生垃圾还是占资源
String s11 = "";
Random rand = new Random();
StringBuilder result = new StringBuilder();
for (int i = 0; i < 10; i++) {
result.append(rand.nextInt(1000)).append(" ");
}
System.out.println(s11);
//上面代码反编译后:
//StringBuilder result = new StringBuilder();
//for(int i = 0; i < 10; i++){
//result.append(rand.nextInt(1000)).append(" ");};
//创建StringBuilder在for语句外,效率更高,资源消耗少
//注意尽量不用同时使用"+"和StringBuilder否则会重新创建对象
//四
//将上面代码在JDK1.4以下编译,必须将StringBuilder改为StringBuffer
//因为JDK1.4以下没有StringBuilder
//五String,StringBuffer,StringBuilder区别?
/*
区别:
可变不可变
Strnig:字符串常量,修改也不会改变本身而是创建新字符串对象
StringBuffer:修改会改变本身
线程是否安全
String:被定义后不可变,安全
StrinBuffer:安全(同步锁),效率低
StringBuilder:不安全
共同点:
StringBuffer和StringBuilder的父类都是AbstractStringBuilder
他们都会调用父类的append()
*/
System.out.println("----------Integer-----------------");
Integer s12 = 100,s13 = 100,s14 = 150,s15 = 150;
System.out.println(s12==s13);
System.out.println(s14==s15);
//如果整型字面量的值在-128 到 127 之间,
//那么不会 new 新的 Integer 对象,而是直接引用常量池
//中的 Integer 对象
}
当我们执行System.out.println();
的时候
会加载System这个类
这个类有这个方法:
这个方法有一行代码是:sun.misc.Version.init();
初始化sun.misc.Version
进去这个类
就会发现java字符串被定义了
淦
我们自己定义的java在字符串常量池里就是这个java
所以是false
以下是出处::::::::