java堆栈

来源:互联网 发布:网易博客知乎 编辑:程序博客网 时间:2024/05/21 19:32

原文有一定错误


1. 栈(stack)与堆(heap)与C++不同,Java自动管理,能直接地设置栈或堆。

2. 栈速度快,存在栈中的数据大小与生存期必须是事先确定的,缺乏灵活性,栈数据可以共享。堆可以动态地分配内存大小,生存期也不必事先告诉编译器,Java的垃圾收集器会自动收走。运行时动态分配内存,速度慢。

3. Java数据类型:

——基本类型(primitive types), int, short, long, byte, float, double, boolean, char,称为自动变量。

如int a = 3; 这里的a是一个指向int类型的引用,指向3这个字面值,存在于栈中。栈中的数据可以共享。int a = 3;首先在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。int b = 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。

——包装类数据,全部存在于堆中,Java用new()语句来显示地告诉编译器。

4. 关于String str = "abc"的内部工作。

引入:常量池(constant pool)——在编译期被确定,并被保存在已编译的.class文件中的一些数据。它包括了关于类、方法、接口等中的常量,也包括字符串常量。Java会确保一个字符串常量只有一个拷贝。——在编译器就确定了。

(1)定义引用变量:String str;

(2) 在常量池查找"abc",没有设新值,接着创建一个新的String类的对象o,并将o的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象o。如果已经有了值为"abc"的地址,则查找对象o,并返回o的地址。

(3)将str指向对象o的地址。值得注意的是,一般String类中字符串值都是直接存值的。但像String str = "abc";这种场合下,其字符串值却是保存了一个指向存在栈中数据的引用!

String str1 = "abc";

String str2 = "abc";

System.out.println(str1==str2); //true只创建了一个对象,而且两个引用都指向了这个对象。


String str1 = "abc";

String str2 = "abc";

str1 = "bcd";

System.out.println(str1 + "," + str2); //bcd,

abcSystem.out.println(str1==str2); //false上例中,

令str1="bcd"时,JVM发现在栈中没有存放该值的地址,便开辟了这个地址,并创建了一个新的对象,其字符串的值指向这个地址。但JVM在运行时根据新值悄悄创建了一个新对象,然后将这个对象的地址返回给原来类的引用。这个创建过程虽说是完全自动进行的,但它毕竟占用了更多的时间。在对时间要求比较敏感的环境中,会带有一定的不良影响。

String str1 = "abc";

String str2 = "abc";

str1 = "bcd";

String str3 = str1;

System.out.println(str3); //bcd

String str4 = "bcd";

System.out.println(str1 == str4); //true

String str1 = new String("abc");

String str2 = "abc";

System.out.println(str1==str2); //false

创建了两个引用。创建了两个对象。两个引用分别指向不同的两个对象。只要是用new()来新建对象的,都会在堆中创建,而且其字符串是单独存值的,即使与栈中的数据相同,也不会与栈中的数据共享。

6. 数据类型包装类的值不可修改。不仅仅是String类的值不可修改,所有的数据类型包装类都不能更改其内部的值。

7. 结论与建议:

(1)使用String str = "abc";的方式,可以在一定程度上提高程序的运行速度,因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc");的代码,则一概在堆中创建新对象,而不管其字符串值是否相等,是否有必要创建新对象,从而加重了程序的负担。这个思想应该是享元模式的思想,但JDK的内部在这里实现是否应用了这个模式,不得而知。

(2)当比较包装类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==。

(3)由于String类的immutable(不可变)性质,当String变量需要经常变换其值时,应该考虑使用StringBuffer类,以提高程序效率。

原创粉丝点击