您的位置:首页 > 其它

String类陷阱深度剖析 -字符串池-栈-堆-equal--tostring--hashcod

2014-04-19 22:48 337 查看
String类陷阱深度剖析 -字符串池-栈-堆-equal--tostring--hashcode-编码utf-16--赋值过程--==比较。

1.与object类的区

2.赋值创建对象的过程

3.string最好是这样赋值:

String str ="aaa"; ==yes

String str =new String("aaa");==not ,因为多创建了对象,GC次数增多。

1、避免隐式的String字符串
String字符串是我们管理的每一个数据结构中不可分割的一部分。它们在被分配好了之后不可以被修改。比如"+"操作就会分配一个链接两个字符串的新的字符串。更糟糕的是,这里分配了一个隐式的StringBuilder对象来链接两个String字符串。

例如:

a = a + b; // a and b are Strings
编译器在背后就会生成这样的一段儿代码:

StringBuilder temp = new StringBuilder(a).
temp.append(b);
a = temp.toString(); // 一个新的 String 对象被分配
// 第一个对象 “a” 现在可以说是垃圾了
它变得更糟糕了。

让我们来看这个例子:

String result = foo() + arg;
result += boo();
System.out.println(“result = “ + result);
在这个例子中,背后有三个StringBuilders 对象被分配 - 每一个都是"+"的操作所产生,和两个额外的String对象,一个持有第二次分配的result,另一个是传入到print方法的String参数,在看似非常简单的一段语句中有5个额外的对象。

试想一下在实际的代码场景中会发生什么,例如,通过xml或者文件中的文本信息生成一个web页面的过程。在嵌套循环结构,你将会发现有成百上千的对象被隐式的分配了。尽管VM有处理这些垃圾的机制,但还是有很大代价的 - 代价也许由你的用户来承担。

解决方案:

减少垃圾对象的一种方式就是善于使用StringBuilder 来建对象,下面的例子实现了与上面相同的功能,然而仅仅生成了一个StringBuilder 对象,和一个存储最终result 的String对象。

StringBuilder value = new StringBuilder(“result = “);
value.append(foo()).append(arg).append(boo());
System.out.println(value);
通过留心String和StringBuilder被隐式分配的可能,可以减少分配的短期的对象的数量,尤其在有大量代码的位置。


参考链接: http://blog.csdn.net/tayanxunhua/article/details/21752781 http://blog.sina.com.cn/s/blog_74924f2401017upe.html http://blog.csdn.net/ahuier/article/details/8213854 http://www.cnblogs.com/donaldjohn/archive/2011/02/27/1966539.html



1.》》String类陷阱深度剖析

String str3 = "bbb";

String str4 = "bbb";

System.out.println(str3 == str4);

结果为true。为什么呢?这里涉及到字符串池String Pool的概念(String pool是在栈中),首先String
str3 = "bbb";先检测字符串池中是否有bbb对象,如果没有,则将字符串对象bbb放入字符串池中去(也就是在字符创池中创建bbb这个字符串对象,并且将创建好的字符串对象bbb的地址返回给str3),这时引用str3指向这个字符串池中的bbb对象。再String str4 = "bbb";检测字符串池中是否有bbb对象,这时已经有了,所以就不会再将新的bbb对象放入字符串池中去了,这时将字符串池中已有的字符串对象地址返回给str4,这时str4引用还是指向原来的字符串池中已有的字符串对象地址,也就是说String
str4 = "bbb";不会再创建一个对象,所以str3和str4指向同一个对象,所以返回true

String Pool(字符串池),Java中需要维护字符串池的是因为在实际开发中经常会遇到String,所以不用每次都在heap中去生成一个对象,而且这个对象用完一般都是丢掉的,所以需要维护字符串池,而且一般字符串写法用这种形式:String
str = "aaa"。

2.》》

StringBuffer类中对toString这个方法进行了重写(原来Object类下得toString方法是打印出地址的),
所以可以调用toString方法来使StringBuffer类型的数据转变为String类型的
不论是整形还是布尔型等等等,与字符串相加,则他们被自动转换为字符串型


String str1 = "abc";

int
a = 100;

boolean
b = true;

System.out.println(str1+a+b);//输出的结果为abc100true

=============== hashcode =====================

Object.hashCode() 就是32位jvm内存地址。

这里会调用Object的toString()方法,结果就是

return getClass().getName() + "@" + Integer.toHexString(hashCode());

===========String,StringBuffer与StringBuilder的区别??=============== http://blog.csdn.net/rmn190/article/details/1492013[/code] 
StringBuffer 与 StringBuilder 中的方法和功能完全是等价的,只是

StringBuffer 中的方法大都采用了 synchronized 关键字进行修饰,因

此是线程安全的,而 StringBuilder 没有这个修饰,可以被认为是线程

不安全的。

StringBuffer 始于 JDK 1.0

StringBuilder 始于 JDK 1.5

从 JDK 1.5 开始,带有字符串变量的连接操作(+),JVM 内部采用的是

StringBuilder 来实现的,而之前这个操作是采用 StringBuffer 实现的。

====================string注意事项-重点推荐=====================

默认编码是UTF-16,可以指定编码

1.String str ="123";

赋值过程:

1.查找string pool中是否存在"123"对象

2.没有就在string pool生成"123"对象,有就返回"123"对象地址

3.把string pool中的"123"对象地址赋值给str.

【字符串池对象 --->赋值】

2.String str = new String("123");

赋值过程:

1.查找string pool中是否存在"123"对象

2.没有就在string pool生成"123"对象,有就返回string pool"123"对象地址

3.在堆中new String对象,new String("123")

3.把new String("123")的堆对象地址赋值给str.

【字符串池对象 -->堆对象 --->赋值】

字符串池对象初始化完了就是final,下次使用时不用重新创建对象啦。

字符串池:可以重用字符串对象,避免频繁地重新创建。

================equal 和 == (原生数据,对象类型(特殊string))====

equal方法的作用:

看类是否重写过,一分为二来说明

1.object 是否引用指向同一个对象,内存地址相等

2.string重写过,是否内容相等

* equal方法的作用:

* 1.对象引用是否相同

* 2.string重写过的,内容是否相同

String的equal方法逻辑过程:

* 1.对象地址 this=object

* 2.字符串大小length

* 3.字符串s1中每个字符与字符串s2中每个字符是否相同

==比较

1.原生数据类型 ===> 数值比较

2.对象类型 ===> 引用地址,对象相等

================关键字 final static =====================

final 一定要初始化,有2个地方来初始化:1.声明时 2.构造方法时

static

1.不能与this合用

2.时机不同。static静态块在.class加载是运行的。实例化对象时运行构造函数

3.执行顺序:静态优先,父辈优先。先当前类的父类的静态块,当前类的静态块,先当前类的父类的构造函数,后当前类的构造函数。

4.执行次数。静态一次,实例化对象可以new多次。

================JVM之类加载器深度剖析=====================

深入详解JVM之类加载器深度剖析、根、扩展及系统类加载器.avi
http://v.youku.com/v_show/id_XMjc1NDEyMzI4.html
类验证:目的=保证安全。

1.文件结构

类声明,类属性,类方法

2.语义检查

3.字节码验证

防止自己手写的class文件

4.二进制兼容性验证

编译的JDK版本不一致。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: