首页 > 解决方案 > Java 内存管理对象与原始类型

问题描述

我对有关 Java 内存管理的几点感到有些困惑。

了解了堆栈和堆之间的区别,我去看了一个适当的例子,说明当我们执行一些代码时这些内存是什么。

我以这几行为例

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;
}

我了解堆栈和堆中发生了什么。该变量没有被返回,在这种情况下没有对堆的引用。

而在这个例子中:

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 包装在 Customer 中,我将得到 50 而不是 5。

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

标签: javamemorymemory-managementjvm

解决方案


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

调用 methodcalculate时,您传递一个引用(在您的情况下,ifrom main)。

诀窍是,Java 将在calculate. 所以iinside ofcalculateiinside ofmain最初可能“指向”同一个对象,但它们不是“相同的”。

因此,如果将iinside of更改calculate为乘法产生的对象,则不会自动更改iinside of的引用main

有了Customer,就不一样了。你永远不会改变cinsetAName点的位置。您更改了对象内部的一个引用,但customer内部main和内部仍然指向该对象csetAName

这里有两张糟糕的油漆图来解释我的意思(前缀数字0x是参考):

对于整数示例:

整数图

对于客户示例:

客户图

如有任何问题,请随时回来。

我希望这有帮助。


推荐阅读