创建Java对象一般问题
哪个对于内存管理或任何其他原因更好,或者这两种情况是否相同:
Calendar currentDateTime = Calendar.getInstance();
int i= foo.getSomething(currentDateTime);
Bar bar= foo.getBar(currentDateTime);
另一个代码块:
int i= foo.getSomething(Calendar.getInstance());
Bar bar= foo.getBar(Calendar.getInstance());
一般问题是,是否更好地获取对象的实例,然后在需要时使用该实例,或者使每次需要时都会调用 getInstance() 。 而且,如果不处理单例,而是制作一个普通的 POJO,答案会改变吗?
Which is better for memory management, or any other reason, or are these two scenarios the same:
Calendar currentDateTime = Calendar.getInstance();
int i= foo.getSomething(currentDateTime);
Bar bar= foo.getBar(currentDateTime);
The other code block:
int i= foo.getSomething(Calendar.getInstance());
Bar bar= foo.getBar(Calendar.getInstance());
The general question is, is it better to get an instance of an object, then use that instance when needed, or make the getInstance() call each time when needed.
And, does the answer change if not dealing with a singleton, but making a plain POJO?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
垃圾收集器可以在最后一次使用对 Calendar 实例的引用后立即收集它。
The garbage collector is free to collect the Calendar instance immediately after the last use of a reference to it.
需要明确的是,Calendar 实际上并不是单例。每次调用 Calendar.getInstance() 时都会返回一个新对象。
这意味着您问题的答案取决于函数 getSomething() 和 getBar() 是否具有导致 foo 存储新 Calendar 实例的副作用。一般来说,良好的编程实践表明情况不会如此。
编辑:但是,每次调用 Calendar.getInstance() 时,您可能会得到不同的日期。这可能是一个重要的细节,具体取决于您的函数正在执行的操作。
编辑 2:它还取决于您执行上述过程的频率。正如另一个答案指出的那样,实例化 Calendar 对象可能会很密集。如果只做两次,那么缓存也没关系。如果您经常这样做,那么您可以考虑改变您的方法或进行一些缓存。
To be clear, Calendar is not actually a singleton. Calendar.getInstance() returns a new object each time you call it.
This means that the answer to your question depends on whether or not the functions getSomething() and getBar() have side effects that cause foo to store the new Calendar instance. In general, good programming practices dictate that this won't be the case.
EDIT: However, each time you call Calendar.getInstance() you could end up with a different date. This may be an important detail depending on what your functions are doing.
EDIT 2: it also depends on how often you do the above process. As another answer pointed out, instantiating Calendar objects can be intensive. If you only do it twice, then it doesn't matter if you cache it. If you do this very often, then you may consider changing your approach or doing some caching.
日历是一个非常昂贵的对象(我所知道的所有库中最昂贵的日期对象之一)。调用 getInstance() 也非常昂贵。如果您必须使用日历,您可以考虑缓存它。这实际上取决于您为什么需要它。
获取和存储当前时间的最有效方法是使用 long 原语。
如果您在内部使用 GMT 时间,则可以使用 EDIT 存储当前日期
:值得在您的计算机上进行测试,而 getInstance() 相对昂贵,但仍然相当快。在我的旧盒子上大约需要 20 微秒。在快速机器上,currentTimeMillis() 可能需要 140 纳秒。
下面打印
代码
Calendar is a very expensive object (one of the most expensive date objects in any library I know of). Calling getInstance() is very expensive too. If you have to use Calendar you could look at caching it. It really depends on why you need it.
The most efficient way to obtain and store the current time is using a long primitive.
If you use GMT time internally, you can store the current day with
EDIT: It is worth testing on your machine, while getInstance() is relatively expensive but it is still fairly fast. On my old box it takes ~20 micro-seconds. On a fast machine currentTimeMillis() can take 140 nano-seconds.
The following prints
code
对于单身人士来说,这没有多大区别。通过使用临时变量,您可以节省函数调用的开销,但仅此而已 - 每次都返回相同的对象。
如果您正在创建 POJO,无论是通过调用构造函数还是使用对象创建静态方法,您都在创建一个新对象。这意味着您有函数调用的运行时开销,以及创建的另一个对象的内存开销。
一般来说,如果我计划在方法体内多次使用同一个对象,我将使用临时变量。这样,无论是否需要避免内存开销,我都会做同样的事情,并且我的代码将更加一致。
For a singleton, it doesn't make much of a difference. By using a temporary variable, you are saving the overhead of a function call, but nothing more - the same object is being returned each time.
If you are making a POJO, either by calling a constructor or by using an object-creation static method, you are creating a new object. This means that you have the run-time overhead of a function call, as well as the memory overhead of another object being created.
In general, if I am planning on using the same object several times within a method body, I will use a temporary variable. This way, I am doing the same thing whether I need to avoid memory overhead or not, and my code will be more consistent for it.
您必须决定要为操作提供什么。
您的应用程序的瓶颈是什么。
You have to decide what you want to give for the operation.
What is the bottleneck in your application.
您基本上正在考虑两种不同的场景:
1. Calendar 是单例,在这种情况下,您将必须调用辅助方法来获取内存中的单个实例。
2.日历是一个POJO。如果 getInstance() 只是调用构造函数,那么每次调用它时都会创建一个新实例。因此,在后一种情况下,您可能会得到不同的意外结果。
但最重要的是,它取决于编码风格和可读性。有些开发人员更喜欢使用工厂方法,有些开发人员更喜欢直接调用构造函数。在我看来,如果对象是一个简单的实体(即不需要构建),那么调用 new 是创建对象的最直接的方法。另一方面,如果涉及一些构建,并且您通常需要更具可读性的代码,那么工厂方法是更优选的。
从内存管理的角度来看,每次调用构造函数时,您都会获得该类的一个新实例。您要使用那个新实例吗?您是否有对该新实例的引用,可能会阻止其及时被垃圾收集?这些问题有点元。
You are basically looking at two different scenarios:
1. Calendar is a singleton, in which case you will have to call a helper method to get the single instance that is in memory.
2. Calendar is a POJO. If getInstance() simply calls the constructor, then you will be creating a new instance every time you invoke it. As such, you may be getting different unexpected results in your latter case.
The bottom-line, though, is that it comes down to coding-style and readability. Some developers prefer using factory methods, some prefer simply calling the constructor directly. In my mind, if the object is a simple entity (i.e. no build-up required), then calling new is the most straight-forward method of creating an object. If, on the other hand, there is some build-up involved, and you want generally more readable code, then a factory method is much more preferred.
From a memory-management perspective, every time you call the constructor, you will get a new instance of the class. Are you going to use that new instance? Do you have references to that new instance that might keep it from being garbage collected in a timely manner? Those questions are a bit more meta.
如果您只对读取日历实例感兴趣,则第一种方法稍微好一些,因为垃圾收集器不会有太多工作要做,并且您只会存储/制作一次重量级对象。
If you are only interested in reading from the calendar instance the first method is marginally better, since the garbage collector won't have quite so much work to do, and you will only be storing/making a heavyweight object once.
第一个块查询当前日期和时间一次。这很好,因为您可能想对两者使用相同的时间戳。
第二个示例速度较慢,因为它必须初始化一个新的
Calendar
对象。也可能有两个不同的时间戳。问问自己,当第一个方法在23:59:59.875
的时间调用并且第二个方法在00:00:00.007
的时间调用时,午夜左右会发生什么>。你真的想要那个吗?从技术上和严格意义上讲,第一个代码片段占用了一些较长时间的内存。但在几乎所有情况下,您都应该接受并使用第二个代码片段。
顺便说一句:您可以假设局部变量不消耗任何内存。特别是在经常使用的代码中,它们将被优化掉。
The first block queries the current date and time once. This is good, since you probably want to use the same timestamp for both.
The second example is slower since it has to initialize a new
Calendar
object. Also there may be two different timestamps. Ask yourself what will happen around midnight when the first method is called with a time of23:59:59.875
and the second method is called with a time of00:00:00.007
. Do you really want that?Technically and strictly the first code snippet claims some memory for a longer time. But in pretty much all cases you should be fine with that and go with the second code snippet.
And by the way: You can assume that local variables don't cost any memory. Especially in often-used code they will be optimized away.