堆、栈、==、equals

2017-03-02  本文已影响35人  敲代码的本愿

栈与堆是JavaRam中存放数据的地方,由Java自动管理,不能直接设置。

堆 heap##

是一个运行时数据区,类的对象从中分配空间。由垃圾回收器管理。

对象:
通过new、newarray、anewarray、multianewarray等指令建立,不需程序代码来显式的释放。

JDK 5.0前,Integer i = 3;表达式是不被允许的,因为类与字面值不能通用,除String
JDK 5.0后,可以这么写,编译器在后台进行Integer i = new Integer(3);转换。

优点#####

1、动态地分配内存大小;
2、生存期不必事先告诉编译器。因为是在运行时动态分配内存,垃圾回收器会自动回收不再使用的数据。

缺点#####

由于在运行时动态分配内存,存取速度较慢。

栈 stack##

是一个先进后出的数据结构,存放基本类型的变量和对象的引用变量(类实例)。

基本类型(primitive types)
共8种:int, short, long, byte, float, double, boolean, char(无string基本类型)。

自动变量
基本类型通过诸如int a = 3;的形式来定义,称为自动变量。
自动变量存的是字面值,非类的实例(不是类的引用,也没有类存在)。a是一个指向int类型的引用,指向3这个字面值。

字面值的数据,由于大小可知,生存期可知(固定定义在某个程序块里面,程序块退出则字面值消失),故存在栈中。

优点#####

1、存取速度比堆要快,仅次于寄存器;
2、数据可以共享。

缺点#####

存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。

数据共享#####

int a = 3;
int b = 3;
编译器先处理int a = 3;
1、在栈中创建一个变量为a的引用;
2、查找栈中是否有3这个值,若没有,则将3存进栈中,将a指向3
接着处理int b = 3;
3、在栈中创建一个变量为b的引用;
4、查找栈中是否有3这个值,因栈中已有,则将b直接指向3
5、此时,令a = 4;编译器会搜索栈中是否有4值,若没有,则将4存进栈中,将a指向4;若有,直接将a指向4
因此a值的改变不会影响到b值,由编译器完成,有利于节省空间。

总结###

==、equals##

== 比较的是值【变量(栈)内存中存放的对象的(堆)内存地址】
equals
1、非包装类数据:等同于==
2、包装类数据:比较两个对象的值是否相同【堆内存中的内容】

==equal运行速度快,因为"=="只是比较引用。

包装类数据
Integer、String、Double等将相应的基本数据类型包装起来的类。这些类数据存放在堆中

源码#####

Object类中的equals方法和==一样,引用数据类型重写了equals方法。

//Object类中equals方法
public boolean equals(Object obj) {
    return (this == obj);
}
//String类重写的equals方法
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String) anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}
String 类#####

String类由final修饰,不能被继承,是不可变类。

对象创建完成后,正常情况下,对象的状态不会因外界的改变而改变(对象的状态指对象的属性,包括属性的类型及属性值)。

String str = "abc";
System.out.println(str);  // abc
str = "def";
System.out.println(str);  // def

str是存储在栈内存中指向堆内存中的引用,即存储的是对象在堆中的地址,而非对象本身。
此时堆内存中依然存在abcdef对象。对于abc对象本身而言,对象的状态没有发生任何变化。

String是一个特殊的包装类数据。

//两种创建方式
(1)String str = new String("abc"); 
(2)String str = "abc"; 

第一种:用new()创建的对象存放在堆中。每调用一次便创建一个新的对象。
第二种:先在栈中创建String类的对象引用变量str,并在堆中创建对象abc

//示例
String str1 = new String ("abc");
String str2 = new String ("abc");
System.out.println(str1==str2); // false
System.out.println(str1.equals(str2)); //true 
//str1、str2分别创建了一个abc对象

String str1 = "abc"; 
String str2 = "abc"; 
System.out.println(str1==str2); //true 
System.out.println(str1.equals(str2)); //true 
//abc对象只在创建str1时创建,创建str2时并未创建新的abc对象,但指向str1创建的abc

String str1 = new String("abc"); 
String str2 = "abc"; 
System.out.println(str1==str2); //false 
System.out.println(str1.equals(str2)); //true 
//str1、str2分别创建了一个abc对象
上一篇 下一篇

猜你喜欢

热点阅读