2016-01-02 79 views
2

我知道Java是通过引用或按值传递的问题正在击败死马,但我确实有关于内存使用情况的问题。在变量之间传递大量数据时最大限度地减少内存使用量

我理解Java现在的方式是:

public class MyInt{ 
    int value; 
} 

MyInt x; 
MyInt y; 
x = new MyInt(3); // value of x is now 3 
y = x;    // y now points to same object that x points to 
y.setValue(1);  // value of said object is now 1 
x.getValue();  // should return 1 instead of 3 

但我的问题是内存密集型它是如何设置这个新y?例如:如果明特的数值是一些非常非常大的图像,而不是一个整数,

x = new MyImage("very large image"); // eats memory depending on size of image 

自然会占用大量的内存有图像加载如果它是非常大的。我只是想确保当我打电话

y = x; // y now points to same image that x does 

y只是到x右侧已经指向的对象的引用?所以当我拨打y = x;只要该图像已经通过初始化x加载,无论图像有多大都不会造成内存密集。

这是正确的吗?我应该避免将同一个非常大的图像多次加载到内存中的哪些缺陷?

+0

如果您担心可能多次使用_same_参数调用'new MyImage(“some string”)',并且它会创建同一大图的多个副本,那么您可以使用缓存来避免问题。像HashMap这样的'Map'将是维护这种缓存的一种简单方法。 – ajb

+0

'这是否正确?' - 是的,y和x只保存大对象的内存地址。内存地址在大多数系统上是一个整数(小)。 –

回答

0

你是对的,当你打电话给y=x它会简单地设置y来指代“非常大的图像”的位置。内存中仍然只有1个对象,它们将被xy引用。

为避免在存储器中一次又一次加载非常大的图像,只是不要再次使用该图像创建新对象。避免深层复制对象。

3

是的你是对的,任何非原始引用变量的非原始实例赋值都只是引用赋值。

因此,如果有一个内存位置为x说mem1那么y = x将使y指向mem1。现在,即使x指向一个新的内存位置mem2,y仍然会指向mem1。所以这是一个需要避免的陷阱。

您几乎永远无法加载一个非常大的对象多次而不会先知道它,因为您要么创建调用构造函数的新对象,要么使用某种形式的clone()方法。

与大型对象无关但与Java中的引用相关的一个陷阱是传递给方法的引用变量不能被取消引用。

所以假设有一个方法dereferenceMe(MyInt x) {x = new MyInt();}它不会改变调用方法中x的实际引用。由于Java将通过值传递引用,这意味着它会创建引用变量的副本,并将该副本传递给方法。

+0

关于解引用的最后一点。这是否意味着你现在有两个MyInt引用? –

+0

是的,一个在调用者方法中,另一个在调用方法中。 – 11thdimension

+0

在c#等其他编译语言中,它的工作原理是否相同? –

相关问题