当前位置: 首页 > >

Java 引用,栈 堆 的理解

发布时间:


栈有一个很重要的特殊性,就是存在栈中的数据可以共享。假设我们同时定义:

int a=3;

int b=3;

编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b = 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址

Java用new()语句来显示地告诉编译器,在运行时才根据需要动态创建,因此比较灵活,但缺点是要占用更多的时间.


另一种是包装类数据,如Integer, String, Double等将相应的基本数据类型包装起来的类。这些类数据全部存在于堆中,Java用new()语句来显示地告诉编译器,在运行时才根据需要动态创建,因此比较灵活,但缺点是要占用更多的时间。

1、栈:?存放基本数据类型及对象变量的引用,对象本身不存放于栈中而是存放于堆中

1)、基础类型 byte (8位)、boolean (1位)、char (16位)、int (32位)、short (16位)、float (32位)、double (64位)、long (64位)

2)、java代码作用域中定义一个变量时,则java就在栈中为这个变量分配内存空间,当该变量退出该作用域时,java会自动释放该变量所占的空间

2、堆:?new操作符的对象

1)、new创建的对象和数组

2)、在堆中分配的内存,由Java虚拟机的自动垃圾回收器来管理

3、静态域:?static定义的静态成员变量

4、常量池:?存放常量

1 String a = "hello"; //先在栈中创建一个对String类的对象引用变量a,然后通过符号引用去字符串常量池里找有没有"hello",如果没有,则将"hello"存放进字符串常量池 ,并令a指向"hello",如果已经有"hello"则直接将a指向"hello" --> 产生1个对象及1个引用
2 String b = "hello"; //先在栈中创建一个对String类的对象引用变量b,然后通过符号引用去字符串常量池里找有没有"hello",因为之前在常量池中已经有"hello",所以直接将b指向"hello" --> 因为不需要在常量池产生"hello",所以只是在栈中产生1个引用
3 String newA = new String("hello"); //先在栈中创建一个对String类的对象引用变量newA,然后new()操作会在heap堆中产生一个新的对象"hello",并将newA指向堆中的"hello",同时检查String pool常量池中是否有对象"hello",如果没有也产生一个对象"hello",如果有则不产生,因为这里之前已经在常量池中产生过了,所以 --> 只需要产生1个对象及1个引用
4 String newB = new String("hello"); //因为new每次都会保证在heap堆内存中产生新的对象,并将栈中的引用指向对应的堆中的地址,所以此语句同上一条的处理

?

三 、String实例代码分析




1 package terry.java.base;
2
3 public class StringTest {
4 public static void main(String[] args) {
5 String a = "hello";
6 String b = "hello";
7
8 String newA = new String("hello");
9 String newB = new String("hello");
10
11 System.out.println("****** Testing Object == ******");
12 System.out.println("a==b ? :" + (a==b));
13 System.out.println("newA==newB ? :" +(newA==newB));
14 System.out.println("a==newA ? :" + (a==newA));
15
16 System.out.println("***** Testing String Object intern method******");
17 System.out.println("a.intern()==b.intern() ? : " + (a.intern()==b.intern()));
18 System.out.println("newA.intern()==newB.intern() ? :" + (newA.intern()==newB.intern()));
19 System.out.println("a.intern()==newA.intern() ? :" + (a.intern()==newA.intern()));
20 System.out.println("a=a.intern() ? :" + (a==a.intern()));
21 System.out.println("newA==newA.intern() ? : " + (newA==newA.intern()));
22
23 System.out.println("****** Testing String Object equals method******");
24 System.out.println("equals() method :" + a.equals(newA));
25
26 String c = "hel";
27 String d = "lo";
28 final String finalc = "hel";
29 final String finalgetc = getc();
30
31 System.out.println("****** Testing Object splice ******");
32 System.out.println("a=="hel"+"lo" ? :" + (a=="hel"+"lo"));
33 System.out.println("a==c+d ? : " + (a==c+d));
34 System.out.println("a==c+"lo" ? : " + (a==c+"lo"));
35 System.out.println("a==finalc+"lo" ? :" + (a==finalc+"lo"));
36 System.out.println("a==finalgetc+"lo" ? :" + (a==finalgetc+"lo"));
37
38 }
39 private static String getc(){
40 return "hel";
41 }
42 }View Code

Run As Java Application -- 输出结果:




1 ****** Testing Object == ******
2 a==b ? :true
3 newA==newB ? :false
4 a==newA ? :false
5 ***** Testing String Object intern method******
6 a.intern()==b.intern() ? : true
7 newA.intern()==newB.intern() ? :true
8 a.intern()==newA.intern() ? :true
9 a==a.intern() ? :true
10 newA==newA.intern() ? : false
11 ****** Testing String Object equals method******
12 equals() method :true
13 ****** Testing Object splice ******
14 a=="hel"+"lo" ? :true
15 a==c+d ? : false
16 a==c+"lo" ? : false
17 a==finalc+"lo" ? :true
18 a==finalgetc+"lo" ? :false

String a = "hello";
6 String b = "hello";
7
8 String newA = new String("hello");
9 String newB = new String("hello");
因此a.intern(),b.intern(),newA.intern(),newB.intern()隐含的各自在栈中分配了各自的内存区域,同时都将栈中的应用全部指向了String pool常量池中的同一块区域"hello"



友情链接: