初探对象在内存储器中的创建

初探对象在内存中的创建
初探对象在内存中的创建:
   我们先了解一下JAVA在内存中的如何实行对象的创建机制的。在内存中是创建四个区来实现对象的创建和加载机制的。
1.是heap(即堆区):它是负责创建对象的,所有的创建出来的对象都是放在堆区的。
2.是stack(即栈区):它是负责存放局部变量,和成员变量的。所有的成员变量和局部变  量都放在这个区内,然后他通过一个引用指向栈区的对象或data segment(静态代码)区的静态数据。
3.data segment(静态代码区):在这个区主要存放的是静态常量,和字符串常量。在类一开始被加载的时候此常量就被初始化放在这个区内,而且被全局所共享,所有的访问直接指向他即可。
4.code segment(代码区):它是存放代码的区,所有的执行代码都放在此区内。通过对象的调用指向此区。
说了这么多了,我们举例说说:
首先写一个类public class Cat{
int weight;
string name;
Cat(int weight,String name){
this.weight=weight;
this.name=name;
}
}
那我们先创建俩个对象Cat c1=new Cat(12,"mimi");
                 Cat c2=new Cat(12,"mimi");
那么请问 c1==c2 返回是false还是true;那么c1.equals(c2);返回是false还是true呢?
通过运行结果是都为false; 因为他们是堆区创建的俩个对象。所以==返回的是false;而equals是判断他们在堆空间的内存地址是否相等。显然不相同
/*------------------------
在它的API文档中是这样写的:
equals 方法在非空对象引用上实现相等关系:

自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
对于任何非空引用值 x,x.equals(null) 都应返回 false。
---------------------------*/

从中我门可以看出如果每有重写equals()方法时是不相同的。
但是在我们开发中往往需要的是判断俩个对象是否他们的内容是否一致,是否相同。并不会考虑他们的内存地址是否相同。解决这类问题往往需要重写他的equals()方法:那么我们现在重写上面那个类的equals()方法在进行判断。
@Override
public boolean equals(Object obj)
{
   if(obj == null) return false;
   else
   {
if(obj instanceof Cat)
         {
  Cat c = (Cat)obj;
  if(c.color == this.color && c.height == this.height && c.weight == this.weight)
           {
return true;
   }
          }
    }
      return false;
}
那么我们现在再进行比较的话你们说c1==c2 返回是false还是true;那么c1.equals(c2);返回是false还是true呢?
当然是前者是false。后者是true;
这主要是重写了他的equals()方法了。但对于一般的容器类不光要重写它的equals()方法,还要重写它的hasCode()方法才行,这里就不作讨论了。

-----------------------------------
注意:这java的API文档中并不是所有的类都要重写equals()方法的。像String类,date类等等;都已经重写了她自己的equals()方法了,不需要你在重写它了。
这里有几个有意思的小例子大家看看你都了解了吗?
----------------------为了省事类的定义我就不写了。
-----创建String变量
String s1="hehe";
String s2="hehe";
String s3="hello ";
String s4="world";
String s5="hello world";
String s6=s3+s4;
---------创建String对象
String s7=new String("hehe");
String s8=new String("hehe");
String s9=new String("hello ");
String s10=new String("world");
String s11=new String("hello world");
String s12=s9+s10;
------结果验证
System.out.println(s1==s2); //true
System.out.println(s1.equals(s2));//true
System.out.println(s5==s6); //false
System.out.println(s5.equals(s6)); //ture
System.out.println(s7==s8); //false
System.out.println(s7.equals(s8));//true
System.out.println(s3==s9);//false
System.out.println(s3.equals(s9));//true
System.out.println(s11==s12);//false
ystem.out.println(s11.equals(s12));//ture
-------------------------
通过以上实验我们可以看出String 类型的变量和String 类型的对象的创建它的equals()方法都是返回true;这我们在上面说过了,她自己本身已经重写了equals()方法了。所以不需要我们在重写了。也就是说它所判断的是内容,而并不是它们在内存的地址,而==就是判断他们的他们的是他们是否指向的同一个变量或对象。System.out.println(s1==s2); //true 为什么这个返回的是true呢? 因为我们知道在data segment(静态代码区)里有一个字符串池,所有变量初始化出来的字符串都放在这个池子里,我们需要访问的时候直接把一个引用直接指向它即可。它是共享的,且只有一份。所以System.out.println(s1==s2); //true
不知道你明白没有。

--------------------------------
呵呵,我是第一次写,所以有什么不对的地方或什么不妥的地方希望大家给予指出,
大家共同学习!今天就写到这吧!