package hashcode; public class LearnString { public static void main(String[] args) { //1.先在栈中创建一个对String类的对象引用变量str //2.然后查找堆中常量池(内存中以表存在)里有没有存放"abc" //3.如果没有,则将"abc"存放进常量池,并令str指向”abc” //4.如果已经有"abc"则直接令str指向“abc”。 String str1 = "abcdefg";//在编译期时就确定了 //1. 首先在堆(不是常量池)中创建一个包含指定内容的字符串对象,并将字符串引用指向该对象。 //2. 去字符串常量池中查看,是否有包含该内容的对象。 //3. 若有,则将new出来的字符串对象与字符串常量池中内容相同的对象联系起来。 //4. 若没有,则在字符串常量池中再创建一个包含该内容的字符串对象,并将堆中的对象与字符串常量池中新创建出来的对象联系起来。 //5.栈中的str2总是指向的是堆中的String对象 String str2 = new String("abcdefg"); // 1.== 比较的是地址 System.out.println(str1 == str2);// false // 2.String重写了Object的equals(). System.out.println(str1.equals(str2));// true // 3.java规定,equals()相等,hashcode必须相同,所以String也重写了Object的hashcode(),不然可能有bug. System.out.println(str1.hashCode()==str2.hashCode());//true str2=str2.intern(); //String intern()为每个字符序列生成唯一的String引用 System.out.println(str1==str2);//true String str3="abc"+"defg"; System.out.println("str3:"+(str1==str3));//true 只是因为在编译期,自动优化为abcdefg } }
//在Object中equals(),hashcode().使用native关键字说明这个方法是原生函数,也就是这个方法是用C/C++语言实现的,并且被编译成了DLL,由java去调用 public boolean equals(Object obj) { return (this == obj); } public native int hashCode();
//String中重写的equals(),hashcode public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String anotherString = (String)anObject; int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; } public int hashCode() { int h = hash; if (h == 0 && value.length > 0) { char val[] = value; for (int i = 0; i < value.length; i++) { h = 31 * h + val[i]; } hash = h; } return h; }