Java中的内存管理 [英] Memory-management in java

查看:92
本文介绍了Java中的内存管理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


我有这两个代码:


I have this two codes:

A a = new A();
B b = a.getB();


B b = new A().getB();

在第一个代码中,我创建了两个对象并保存,因此程序需要为两个对象存储内存
但是在第二个代码中,我从A创建了对象,但我没有将其保存在任何变量中,所以我的问题是:
这两个代码有什么区别?仅仅是语法还是对内存有影响?

In the first code I created two objects and saved them so the program need memory for two objects
but in the second code I created object from A and I didn't saved it in any variable so my question is :
what is the different between this two codes? is it just a syntax or there is an effect on memory?

推荐答案

参考/指针与对象

您的保存"一词没有技术含义,可能会使您感到困惑.

Reference/Pointer versus Object

Your term "saved" has no technical meaning, and may be confusing you.

让我们更加具体.将A类替换为Cat类.将B类替换为Breed类.

Let’s get more concrete. Replace A class with Cat class. Replace B class with Breed class.

让我们假设在实例化Cat时,我们还实例化了保存在该Cat对象中的Breed对象.换句话说,我们不是在 中这样做延迟加载例子.因此,当实例化Cat时,我们将Breed的实例传递给构造函数.

Let's assume that when instantiating a Cat we also instantiate a Breed object held within that Cat object. In other words, we are not doing lazy-loading in this example. So when instantiating a Cat, we pass along an instance of Breed to the constructor.

Cat a变量不保存Cat对象,它保存对在内存中其他位置构造的Cat对象的引用(指针). Cat对象在内存中的位置,基本上是一个数字,是Cat a保持的位置.

The Cat a variable does not hold a Cat object, it holds a reference (a pointer) to the Cat object that was constructed elsewhere in memory. That location of the Cat object in memory, basically a number, is what is held by the Cat a.

Cat a = new Cat( "Fluffy" , new Breed( "Tabby" ) ) ;  Passing new instance of `Breed` to constructor of `Cat`, with resulting `Cat` object’s location in memory being returned to the `a` reference/pointer variable.

您可以将这段代码想成这样:

You can think of that line of code as this:

Pointer-holding-memory-location-of-object-of-class-Cat a = Instantiate-a-new-Cat-object-somewhere-in-memory-and-return-its-memory-location( … ) ;

概念图:

请注意,访问Breed对象的唯一方法是通过Cat对象Fluffy.我们的代码到达该Cat对象的唯一方法是通过名为a的引用/指针变量.

Notice that the only way to access the Breed object is to go through the Cat object Fluffy. The only way our code can get to that Cat object is through the reference/pointer variable named a.

Breed b = a.getBreed() ;  // Accessing the `Cat` instance, then traversing to the `Breed` object.

在该代码之后,我们已经分配了少量的内存来保存另一个名为b的指针/引用. b变量不是Cat也不是Breed,它是在内存中其他位置找到Breed对象的存储位置.现在,我们可以直接访问Breed对象,而无需通过Cat实例.

After that code we have wee bit of memory now allocated to holding another pointer/reference, the variable named b. The b variable is not Cat nor a Breed, it is the memory location of where to find the Breed object elsewhere in memory. We can now directly access the Breed object, without going through the Cat instance.

概念图:

您的其他代码:

B b = new A().getB() ;

…转换为我们的示例:

Breed b = new Cat( "Fluffy" , new Breed( "Tabby" ) ).getBreed() ;

...非常相似,但从未将引用a建立为命名变量.至少在概念上生成了 引用(实际上,JVM可能有优化).短暂的简短参考用于立即调用getBreed方法.

…is quite similar, but never establishes the reference a as a named variable. The reference is generated, at least conceptually (in actuality a JVM may have optimizations). The brief ephemeral reference is used to immediately call the getBreed method.

在获得Breed对象的内存位置之后,将释放对新Cat对象的临时引用,并且新的Cat对象将超出范围.从技术上讲,新的Cat对象可能仍会暂时停留在内存中,从而成为的候选对象.垃圾收集,因为它会从内存中清除.

After obtaining a memory-location of the Breed object, the ephemeral reference to the new Cat object is released, and the new Cat object falls out of scope. The new Cat object technically is likely still floating in memory for a moment, becoming a candidate for garbage-collection, due to be purged from memory.

当然,上面使用CatBreed看到的新的单层代码变得很愚蠢:我们实例化一个新的Breed,将其传递给Cat的构造函数,然后立即要求将其取回.为了讨论内存管理问题,让我们忽略笨拙的愚蠢行为.

Of course the new one-liner seen above using Cat and Breed becomes silly: We instantiate a new Breed, pass it to the constructor of Cat, and then immediately ask to get it back. Let’s ignore the awkward silliness for the sake of this memory-management discussion.

概念图:

对于内存管理,在两种情况下都可能占用相同的内存量(取决于JVM的实现).两种情况都在建立一对对象和一对引用.一个小的区别是,在第二种情况下,Cat对象及其临时指针立即超出范围,并成为垃圾收集的候选对象.因此,内存可能的回收速度要比第一种情况更快.实际上,差异可能很小.

As for memory management, the same amount of memory is likely taken in both your scenarios (depending on your JVM implementation). Both scenarios are establishing a pair of objects and a pair of references. The one slight difference is that in your second scenario the Cat object and its ephemeral pointer go out of scope immediately, and become candidates for garbage-collection. So memory might be reclaimed sooner than in your first scenario. In practice, the difference would likely be insignificant.

正如其他人所评论的,所有这些仅仅是学术上的.您通常不必担心这种微优化.

As others commented, all this is merely academic. You generally should not worry about such micro-optimizations.

现代的编译器和JVM进行了非常出色的优化,这是有史以来最优化和测试最充分的大型软件项目.因此,编写Java代码的最佳方法就是简单.为人类编写简单易懂的代码,您还将编写最有可能被编译器和JVM优化的代码.超越编译器的想法而变得聪明&具有讽刺意味的是,JVM可能适得其反,从而导致代码优化程度较低.

The modern compilers and JVMs are extremely well-optimized, some of the most well-optimized and well-tested large software projects ever. So the best way to write Java code is simply. Write simple easy-to-read and easy-to-understand code for humans, and you will also be writing code that is most likely to be well-optimized by the compiler and JVM. Trying to be clever by out-thinking the compiler & JVM is ironically liable to be counter-productive, resulting is less-optimized code.

这篇关于Java中的内存管理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆