String类生成对象剖析
程序员文章站
2022-03-02 14:17:25
...
String是java中用的频率最高的类,可真正理解其内部对象创建机制的人不多,本文就将对其对像创建机制做个小小的总结,若有不对的地方还往各位资深人士多多指教。。。
1.String类是final的,所以你不可能通过面向对象的多态机制去重载或者重写他的方法。
2.String对象被设计成immutable,被创建后的对象原则上是不能被改变的,一个唯一的办法就是通过java的反射机制去改变String对象的值,但这样往往存在着一些隐患,比如你重新赋值后的value值超过本来String对象的长度,将得不到你理想的结果,所以原则上是不提倡去改变String对象的值。
3.在jvm规范中,明确所有的java类都维护了一个叫做常量池的数组用以存储Class中各种常量,String constant赫然在列,所以在创建java对象时首先是在常量池中创建一个String对象,如果采用new String("abc"),那么在常见一个常量池中的String对象之后,将这个对象拷贝一份,放到heap里,所以上面的语句创建了两个String对象,当然jvm会先探测常量池中是否已经存在这个对象!
4.在对String对象进行比较的时候,==比较内存地址,equals比较String对象中字符数组的真正内容,
5.在对String对象调用HashCode的时候,只有在第一次调用的时候生成唯一的哈希值,再次调用Hash值将不会重新生成,所以你在通过反射机制改变对象的值的时候不会重新为该对象设置新的hash值
6.实例
1.String类是final的,所以你不可能通过面向对象的多态机制去重载或者重写他的方法。
2.String对象被设计成immutable,被创建后的对象原则上是不能被改变的,一个唯一的办法就是通过java的反射机制去改变String对象的值,但这样往往存在着一些隐患,比如你重新赋值后的value值超过本来String对象的长度,将得不到你理想的结果,所以原则上是不提倡去改变String对象的值。
3.在jvm规范中,明确所有的java类都维护了一个叫做常量池的数组用以存储Class中各种常量,String constant赫然在列,所以在创建java对象时首先是在常量池中创建一个String对象,如果采用new String("abc"),那么在常见一个常量池中的String对象之后,将这个对象拷贝一份,放到heap里,所以上面的语句创建了两个String对象,当然jvm会先探测常量池中是否已经存在这个对象!
4.在对String对象进行比较的时候,==比较内存地址,equals比较String对象中字符数组的真正内容,
5.在对String对象调用HashCode的时候,只有在第一次调用的时候生成唯一的哈希值,再次调用Hash值将不会重新生成,所以你在通过反射机制改变对象的值的时候不会重新为该对象设置新的hash值
6.实例
String s = "Hello";
String s1 = "Hello";
if (s==s1){
System.out.println("Equal without new operator");
}
//你也许会觉得Equal without new operator永远不会被打印,因为==比较的pointer本身而不是value,但由于jvm处理不带new创建String时的重用已经创建好的相同值的对象,所以s==s1是返回true的
String t = new String("Hello");
string u = new String("Hello");
if (t==u){
System.out.println("Equal with new operator");
}
output:Equal without new operator
//new强制创建了两个不同的对象,虽然value一样
上一篇: 死锁编码与定位分析
下一篇: 如何设计一个可读性更强的程序