Java中对象的内存分配问题

1.先看一下一下程序代码:

public class MyClass {

    public static void main(String[] args) {
         String s1 = new String("Hello World!");
         String s2 = new String("Hello World!");
         String s3 = "Hello World!";
         String s4 = "Hello World!";
         int t1 = new Integer(1);
         int t2 = new Integer(1);
         int t3 = 1;
         int t4 = 1;

         System.out.println("两个new String对象:" + (s1 == s2));
         System.out.println("两个String对象:" + (s3 == s4));
         System.out.println("两个new Interger对象:" + (t1 == t2));
         System.out.println("两个int对象:" + (t3 == t4));
    }

}

输出结果如下:

两个new String对象:false
两个String对象:true
两个new Interger对象:true
两个int对象:true

2.查询了一下资料,得到关键字“==”存在如下特性:

基本数据类型(也称原始数据类型):byte,short,char,int,long,float,double,boolean。他们之间的比较,应用双等号(==),比较的是他们的值。
复合数据类型(类):当他们用(==)进行比较的时候,比较的是他们在内存中的存放地址(确切的说,是堆内存地址)。
注:对于第二种类型,除非是同一个new出来的对象,他们的比较后的结果为true,否则比较后结果为false。因为每new一次,都会重新开辟堆内存空间。

3.结论如下:

  • Java中对象主要存储在堆栈(有时简称栈)和堆中。一般用new关键字,会将新建的对象存储在堆中,因此以上的程序实例中,两个new String对象并不相等,但对于基本数据类型,例如boolean,char,byte,short,int,long,float,double等数据类型,Java采用与C和C++相同的方法,不用new来创建变量,而是创建一个并非是引用的“自动变量”,这个变量直接存储“值”,并置于堆栈中,使得这种小的、简单的变量效率变高,这也就是上面的程序实例中,两个new int对象相等,输出为true。
  • 对于非new创建出来的变量,Java会在其字符串常量池(仍位于堆中)创建字符集,然后将对象指向该字符集,当字符串常量池中已有某个字符集时,再次创建“值”相同的对象,指向与前一对象的指向是相同的,这也就是为什么上面两个int和String对象输出都是true

4.关于引用传递,先看如下代码:

public class ManTest {

    int age;
    String name;

    ManTest()
    {
        this.age = 0;
        this.name = null;
    }

    ManTest(int age,String name)
    {
        this.age = age;
        this.name = name;
    }

    public void ShowInfo()
    {
        System.out.println("姓名:" + this.name + ";年龄:" + this.age);
    }

    public void ChangeInfo( ManTest man)
    {
        man.age = 10;
        man.name = "小明";
    }

    public static void main(String args[])
    {
        ManTest man = new ManTest(15,"小红");
        man.ShowInfo();
        man.ChangeInfo(man);
        System.out.println("改变后--------------");
        man.ShowInfo();
    }
}

输入如下:

姓名:小红;年龄:15
改变后--------------
姓名:小明;年龄:10

引用传递的本身是值传递,但这里实际传递的是对象的hashcode,关于hashcode的资料摘抄如下:

hashCode是指对象的散列码,具体值是由对象的hashCode()方法返回的值,,你甚至可以重写该方法让每个对象的hashCode都一样。散列码一般是和HashTable HashMap这种基于散列码的集合有用,用于提高在集合中查询对象的速度。
而内存地址是对象在内存中的位置,一般和hashCode无关。不过Object对象的hashCode方法是个native方法,有可能和对象的内存地址有关。

ChangeInfo函数进行修改,使其输出对象的hashcode值,输出如下,可以看到两者的hashcode是完全相同的:

姓名:小红;年龄:15
传入方法前:1669472530
传入方法后:1669472530
改变后--------------
姓名:小明;年龄:10

由此可以看到,Java引用可以改变实参的内容,但是不能改变实参对象本身。这可以通过以下代码来说明。对ChangeInfo函数和main函数进行如下修改:

public void ChangeInfo( ManTest man)
    {
        System.out.println("传入方法后:" + man.hashCode());
        man = new ManTest(10,"小明");
        System.out.println("改变对象后:" + man.hashCode());
        System.out.println("在类体的方法中,姓名:" + this.name + ";年龄:" + this.age);
    }

    public static void main(String args[])
    {
        ManTest man = new ManTest(15,"小红");
        man.ShowInfo();
        System.out.println("传入方法前:" + man.hashCode());
        man.ChangeInfo(man);
        System.out.println("改变后--------------");
        man.ShowInfo();
    }

输出如下:

传入方法前:2065827189
传入方法后:2065827189
改变对象后:1989444474
在类体的方法中,姓名:小红;年龄:15
改变后--------------
姓名:小红;年龄:15

可以看到,传入的对象没有得到改变。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值