Java 内存

分析Java内存

学习在于总结

分析

对于java来说,内存这一概念对于开发者来说是透明的。Java中的东西都是运行在Java的虚拟机上的,因为Java虚拟机的存在,Java才有了如此之好的跨平台性。但是也就是因为虚拟机的存在,对访问Java的内存就又多了一层障碍,对于开发者来说内存几乎可以说是根本不能够被访问到的。在Java中,也并不希望开发者去访问内存,访问内存并不是安全的,所以根本没有提供给我们去访问内存的API。
但是如果想要观察Java的内存,我们应该怎么办呢?虽然Java中没有提供给我们访问内存的方法,但是Java的Object类中又一个方法hashcode(),这个方法能够给我们返回一个对象的哈希值,这个哈希值是映射到内存的。所以这个对象可以用来表示Java中的内存,当然仅仅只是表示,它并不是Java中对象的内存地址。

Person p = new Person();
p.hashCode();

Java中的对象有了这个方法,可以当做地址来看待,通过它可以比较两个对象是否相同。

        Person p = new Person();
        Person p1 = p;
        Person p2 = p;
        if(p1 == p2)
        {
            System.out.println("true");
        }
        System.out.println(p1.hashCode());
        System.out.println(p2.hashCode());

结果

        Person p1 = new Person();
        Person p2 = new Person();
        if(p1 == p2)
        {
            System.out.println("true");
        }
        System.out.println(p1.hashCode());
        System.out.println(p2.hashCode());

Java的对象可以通过这种方法去映射内存,但是Java中还有一类变量,变量如何去找到内存呢?对于这一点,在Java中每一种类型,都有一个类去对应,例如int可以用Integer去对应等。我们可以将这些类型,赋值给它们对应的类所生成的对象,然后用这个对象去调用hashCode()值。但是这种方法并没有想象中的那么好,并不能得到理想的结果。因为在这里的hashCode()并没有像我们想象中那个样子映射内存地址的,而它表示的是变量中的值。例如:

        int i = 10;
        Integer i1 = i;
        Integer i2 = i;
        if(i1 == i2)
        {
            System.out.println("true");
        }

        System.out.println(i1.hashCode());
        System.out.println(i2.hashCode());

这里写图片描述

        int i = 10;
        Integer i1 = new Integer(i);
        Integer i2 = new Integer(i);
        if(i1 == i2)
        {
            System.out.println("true");
        }

        System.out.println(i1.hashCode());
        System.out.println(i2.hashCode());

这里写图片描述

从这里我们可以看出,hashCode()并没有映射到我们的地址,如果映射到地址的话,两个hashCode()就不可能一样了。所以用hashCode()不能去表示普通类型的地址。

在Integer中,我们的传值过程是值传递。也就是说,Integer变量的内存中所存储的就是一个值,而并不是一个地址,即Integer变量是个值类型的,而不可以看做指针。例如:

        int i = 10;
        Integer i1 = new Integer(i);
        Integer i2 = new Integer(i);
        if(i1 == i2)
        {
            System.out.println("true");
        }
        Integer i3 = chuan(i1);
        System.out.println(i1.hashCode());
        System.out.println(i2.hashCode());
        System.out.println(i3.hashCode());
        static Integer chuan(Integer i)
        {
            i++;
            System.out.println("chuan:"+i.hashCode());
            return i;
        }

结果:
这里写图片描述
i1的值并没有改变,而在子函数中值是发生改变了的。

从中,不知道大家能不能发现一个情况。当然这里是我自己揣测的,如果不对的话,大家可以在评论里为我指出,大家一起来探讨。结论就是:在Java中,虽然没有了指针了这种说法(自我理解应该是Java把指针给封装起来了),但是我们的对象所储存的内容其实也是一个地址,这个地址指向的就是为它开辟的内存空间的地址。在这里,我们是不是就可以理解为hashCode()这个方法,关注的内容是对象所储存的内容,因为自定义类的对象所储存的内容是它指向的地址,所以在我们关注它储存的地址的时候,可以用hashCode()去代替。而Integer这些对象所储存的内容就是一个值,所以我们用hashCode()映射的内容也是这个值,而其实我们想要获取的是int自己的地址,但是通过这种方法我们是获取不到的,并且自定义类对象自己的地址,我们也是获取不到的,如果想要获取的话,可能我们需要的就是二维指针了,可惜遗憾的是Java中并没有二维指针。所以我们不能够获取基本变量的地址,就好比我们不能获取对象自己的地址,只能获取对象所指向的地方的地址,因为对象我们可以近似的理解为指针。

总结

Java中不能够直接操作内存,这样不安全,容易发生意向不到的错误。
以上内容为自己总结,所以肯定有不正确的地方。如果大家发现错误,希望在下面留言。并且欢迎不同意见,也希望在下面留言。最后,希望大家共同进步。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值