栈内存和堆内存Java(详细实例讲解)

定义

栈内存:存放基本类型的变量、对象的引用(引用变量)。(如何回收?)

     在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间:当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用。

堆内存:存放new创建的对象和数组。(GC垃圾回收)

GC垃圾回收:https://blog.csdn.net/sinat_41144773/article/details/89420619

     在堆中产生了一个数组或者对象后,还可以在栈中定义一个特殊的变量(引用变量),这个变量的取值等于数组或者对象在堆内存中的首地址,在栈中的这个特殊的变量就变成了数组或者对象的引用变量,以后就可以在程序中使用栈内存中的引用变量来访问堆中的数组或者对象。数组和对象在没有引用变量指向它的时候,才变成垃圾,不能再被使用,但是仍然占着内存,在随后的一个不确定的时间被垃圾回收器释放掉。这个也是java比较占内存的主要原因

栈内存和堆内存Java(详细实例讲解)_第1张图片

1、基本类型变量的引用和值都存在栈内存,“引用”指向“值”。栈内存的一个特点是数据共享,这样设计是为了减小内存消耗。i=1,i和1都在栈内存内,如果再定义一个j=1,此时将j放入栈内存,然后查找栈内存中是否有1,如果有则j指向1。如果再给j赋值2,则在栈内存中查找是否有2,如果没有就在栈内存中放一个2,然后j指向2。

2、String通过new产生的对象,会先去常量池中查找是否已经有了”word”对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此”word”对象的拷贝对象。由此,String s1 = new String(“word”)会产生几个对象?如果常量池中原来没有”word”,就会产生两个对象!

3、基本类型常量(public static final)存放在常量池中

寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制
栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)
堆:存放所有new出来的对象。
静态域:存放静态成员(static)
常量池:存放字符串常量对象和基本类型常量(public static final)

数据共享性:栈和常量池中的对象可以共享,堆中的对象不可以共享

数据的生命周期:栈中的数据大小和生命周期是可以确定的,当没有引用指向数据时,这个数据就会消失。堆中的对象的由垃圾回收器负责回收,因此大小和生命周期不需要确定,具有很大的灵活性。

引用:https://blog.csdn.net/LK274857347/article/details/77512555

 

2、“==”和equals()的区别

"=="关系操作符的作用:

1、"=="是关系操作符,只能比较两个操作数的值之间的关系

2、用于比较两个基本数据类型的变量指向是否相同,String的直接引号类型是否指向同一个字符串。

      不用于比较看似相同的两个对象,对象间的比较用equals()方法

// "=="操作符的例子
public static void main(String[] args) {
    //基本类型数据,n1和n2在栈内存中都指向5(也在栈内存),可用==比较
    int n1 = 5;
    int n2 = 5;
    System.out.println(n1 == n2);

    //String引用类型,s1、s2都指向常量池中的“word”,可用==比较
    String s1 = "word";
    String s2 = "word";
    System.out.println(s1 == s2);

    //new对象的引用integer1和integer2在栈内存引用地址不同,在堆内存中是两个对象,不可用==比较
    Integer integer1 = new Integer(3);
    Integer integer2 = new Integer(3);
    System.out.println(integer1 == integer2);

    //String new的对象 在堆内存中是两个对象,比较不可用==比较
    String s3 = new String("good");
    String s4 = new String("good");
    System.out.println(s3 == s4);

}

//输出:
true
true
false
false

 

 equals()的作用:

       equals()是Object 中的方法,用于判断两个变量是否是对同一个对象的引用,即堆中的内容是否相同。

// equals()的例子
public static void main(String[] args) {

    Integer integer3 = new Integer(3);
    Integer integer4 = new Integer(3);
    System.out.println(integer3.equals(integer4));

    //String new的对象 在堆内存中是两个对象,比较不可用==比较
    String s5 = new String("good");
    String s6 = new String("good");
    System.out.println(s5.equals(s6));

}

//输出:
true
true

 

结束。

你可能感兴趣的:(Java)