Java内存管理对象与原始类型

时间:2018-12-04 15:43:21

标签: java memory memory-management jvm

关于Java内存管理的几点,我有些困惑。

了解了Stacks和Heap的区别是什么,我去看了一个正确的示例来说明执行某些代码时这些内存是什么。

我以这几行为例

public static void main(String[] args)
{
    int a = 5;
    calculate(a);
    System.out.println(a); //will print 5 not 50
}
private static void calculatee(int a)
{
    a = a * 10;
}

我了解堆栈和堆中正在发生的事情。在这种情况下,不会返回该变量,也没有对Heap的引用。

在此示例中:

public static void maina(String[] args)
{
    Customer customer = new Customer("John");
    setAName(customer);
    System.out.println(customer.getName()); // this will return Philip
}

private static void setAName(Customer c)
{
    c.setName("Philip");
}

这次我可以看到对象的状态发生了改变!

堆栈不是共享的思想线程,而是堆是共享的!在我打印时,目标客户已将其价值从Jhon更改为Philip,这对我来说很有意义! 大!都说得通!

但是,我一直希望我能这样做

public static void main(String[] args)
{
    Integer i = new Integer(5);
    calculate(i);
    System.out.println(i); // printing 5 and not 50
}
private static void calculate(Integer i)
{
    i = i * 10;
}

我会得到50,而不是5!

在这种情况下,Integer是一个对象,我假设它是在堆中创建的!

有趣的是,如果我将Integer包装在Customer中,我将得到50而不是5。

为什么会这样?难道不是在堆中创建了整数类型吗?

1 个答案:

答案 0 :(得分:1)

这是引用问题,而不是堆和栈问题。

在调用方法calculate时,您传递了一个引用(在您的情况下为i的{​​{1}})。

诀窍是Java将在main内创建一个新引用。因此,calculate内的icalculate内的i最初可能“指向”同一对象,但它们不是“相同”。

因此,如果您将main内的i更改为乘法所得到的对象,则不会自动更改calculate内的i的引用

main不同。您永远不会更改Customerc指向的位置。您在对象的内部中更改了一个引用,但是setANamecustomer内部的mainc中的setAName仍指向该对象! / p>

这里有两张简陋的Paint图纸来解释我的意思(以0x开头的数字是参考):

对于整数示例:

Integer Graph

对于客户示例:

Customer Graph

不要犹豫,再提出任何问题。

我希望这会有所帮助。