本文是在浏览论坛时发现很多这样的问题,因此在收集相关的基础上写成的。内容涉及内存存放问题、自动装箱和自动拆箱问题、==和equals问题。

(1)首先看下java中对象的内存存放问题。

代码如下:

 String sa="a string";
String sb=new String("a string");

Integer is=5;
Integer ib=new Integer(5);

//在声明对象时,非常经典的问题是:以上共有几个对象生成?这里留作大家思考吧。

=左面的对象都是存放在堆栈里作为对象引用,而后面的对象信息存放在哪里呢?

 

先看简单的:

String sa=”a string“;

这是一个比较经典的对象声明方法,其中,sa是指向"a string"对象的一个引用,"a string"是其引用对象的内容,其实,"a string"对象和sa对象均存放在堆栈里了。

这里需要强调一点,在JAVA的内存分配机制中,共有两中存储区域:堆栈和堆。其中堆栈存放程序过程,以及对象引用以及基本类型,以及这个古怪的对象String。

在堆栈中,JAVA为了能够让程序员轻松的操作字符串,设立了一个字符串容器--缓冲池。如上例中,当我们声明sa变量的时候,共分为以下几步:首先是由JVM到缓冲池中查找"a string",缓冲池是在每个线程初始化的时候初始的。如果找到了,那么将已存在的"a string"交给sa,如果没有找到,那么将"a string"存放入缓冲池中,并将它的地址付给sa,这样就完成了整个付值操作。

 

(2)自动装箱和自动拆箱问题

 

自java1.5以后有了这两个概念。

 

 

Integer a = 127; //自动装箱(编辑器会隐式处理为:Integer a = new Integer(127); )
        Integer b = 127; //自动装箱(编辑器会隐式处理为:Integer b = new Integer(127); )
        int c = 127; //基本数据类型
         int d = a; //自动拆箱(编辑器会隐式处理为:int d = a.intValue(); )
        double e = a;//自动拆箱(编辑器会隐式处理为:int d = a.doubleValue(); )
        short f = a.shortValue(); //不可以写成:short f = a; 因为隐式转换会丢失精度,必须向上(高精度)转型
        System.out.println(a == c); //自动将a拆箱后,与c进行计算
        //---------------------------------------------

        /**

         * int值在-128~127之间,装箱时,在内存堆中只new一次,则h1,h2指向同一个对象,因此地址== true

         * 但是不在上述的范围时(-128~127),会在内存堆中各个new一次,也就是说,引用地址是不同的,因此== false

         */

 

(3)==和equals问题

==比较的是引用对象的内存地址是否一致,而equals比较的仅仅是属于同一类的对象的属性值是否相等。

对于equals的理解还可以参考Java中Integer的equals()方法的源代码:

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
    }
//其基本思想就是,先判断两对象是不是同一类的实例,然后再判断两对象对应的所有属性值是否相等。

代码1:

String s = "abc";
String t = "abc";
System.out.println(s==t);

/*
输出结果是什么?结果是true,这是根据(1)中的讨论,我们可以较为轻松的得到这个答案,那么请看下面这个例子。
*/

String s = new String("abc");
String t = new String("abc");
System.out.println(s==t);

/*
输出结果为false;我们可以看到,s,t都是通过new的方式创建的,在这里,s,t是存放于堆栈中,他们是指向对象的引用,而两个对象呢,他们都是存放于堆中,作为new出来的正统对象,他们只能呆在堆中。
*/

另一代码:

Integer x = 128; 
	Integer y = 128; 
	Integer compareInt = null; 
	compareInt = x;                                //把x的引用传给compareInt对象,此时,compareInt就等于是x对象		System.out.println(x==y);

	Integer x2 = 127; 
	Integer y2 = 127; 
	Integer compareInt2 = null; 
	compareInt2 = x2;   
       
	System.out.println(compareInt2==y2);//true

 

在(1)(2)问题阐述后,相信问题(3)中的结果就不难理解了。如果还有什么不明白的可以留言讨论。