关于Java String 的些总结

来源:互联网 发布:coincola 知乎 编辑:程序博客网 时间:2024/06/18 07:43

1. String 是引用类型,但它在作为参数传递是值传递,所以一旦修改,会重新指派新的引用,故此时的hashCode(hashCode与地址无关,只与具体的值有关)会发生改变,它的取值是是从StringPool中去获取,如果没有就会创建,并将引用传String对象,请看以下案例

case 1: 到底是值传递还是引用传递

static void replace(String arg){

System.out.println(arg.hashCode());  // 1.

arg = arg.replace("a", "c");

System.out.println(arg.hashCode()); // 2. 此处与1的值不一样

}


public static void main(String[] args){

String arg = "abc";

System.out.println(arg.hashCode());  // 3.此处与1的值一样

replace(arg);

System.out.println(arg.hashCode());  //4.此处与1的值一样

}

请看JDK说明:

     * Initializes a newly created {@code String} object so that it represents
     * the same sequence of characters as the argument; in other words, the
     * newly created string is a copy of the argument string
. Unless an
     * explicit copy of {@code original} is needed, use of this constructor is
     * unnecessary since Strings are immutable.


      case 2: 创建了多少对象

public static void main(String[] args){

String arg = "abc";

System.out.println(arg == "ab" + "c"); // true 其比较原理是,首先会将"ab" + "c" 拼接,在Java中以"ab" + "cd" + "ef"类似情况出现的,都只会创建一个String对象,请注意这里是对象,有人说”ab"是会创建一个String对象,在这里此时创建了4个对象,其实是错的,可以在程序运行时,查看JVM,你会发现在所有的String实例中并没有"ab", "cd", "ef"的实例,只有"abcdef"的实例,充分说明只创建了一个String对象。不难理解在它们没有完成拼接前,它们都不是一个String的实例,只是一个简单的值,那么问题来了,既然不是对象怎么能够拼接运算?怎么能够使用String的方法? 其实这跟Java的编译机制有很大的关系,我们可以查看相应的class文件,你会发现类似下面的信息:

 SOH NUL STXabBS NUL!SOH NUL SOHcBEL NUL#SOH NUL ETB java/lang/StringBuilder

不难发现,在编译时期就已经使用了StringBuilder对象进行运算,并且把“ab" + "c"这种类似的情形当做一个块来处理(STX(块始) ETB(块终)),所以到了运行期间,执行此种类似语句,其实只需要简单值运算下,再将运算的结果放入StringPool,此时便是一个String的对象,接着就可以充当String的实例,不难发现本例中的的 arg == "ab" + "c"其实就是: "abc" == "abc";你说这是不是应该为true.

String arg2 = "ab";

String arg3 = "c";

System.out.println(arg == arg2 + arg3); // false 很奇怪吗,其实一点都不奇怪,arg2 + arg3是运行时计算出来的(这种运算不能与上同日而语),不会放入StringPool池中去,其本身在方法执行栈中,且为暂态(因为没有将其它引用,故这种中间运算结果很快会被释放)


String arg4 = "ab" + "c" ;// 只创建一个对象

String arg5 = "abcde" ;// 只创建一个对象

String arg6 = new String("abcd") ; //创建了2个对象

}

case 3: 有趣的hashCode 和 equals;

其实String对象的hashCode的核心算法,精简了一下

int hash = 0;

value to char array chs;

for: chs

hash = 31 * hash + chs[i]

由此可知,通过比较hashCode也可以判断两个String的对象是否相等,但通常不这样做,也说明了hashCode不等于地址,由此有:

String arg7 = "abc";

String arg8 = "ab";

String arg9 = "c";

System.out.println(arg7.hashCode() == (arg8 + arg9).hashCode()) // true

System.out.println(arg7 == (arg8 + arg9)); // false


eqals方法的核心算法有类似之处:

if another == this.value

then return true;

this.value to char array schs;

another to char array chs;

if(schs.length == chs.length)

for: chs

if(chs[i] == schs[i])

return true;


return false;


 


0 0