Creating Java object general question
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(curre开发者_Python百科ntDateTime);
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?
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.
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.
long currentDateTime = System.currentTimeMillis();
If you use GMT time internally, you can store the current day with
int currentDay = (int)(System.currentTimeMillis() / 86400000);
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
Calendar.getInstance() took on average 20088 ns. java.util.GregorianCalendar[time=1294086899359 ... deleted ...]
System.currentTimeMillis() took on average 938 ns. 1294086899377
code
int runs = 10000;
long start = System.nanoTime();
Calendar cal = null;
for(int i=0;i<runs;i++)
cal = Calendar.getInstance();
long time = System.nanoTime() - start;
System.out.println("Calendar.getInstance() took on average "+time/runs+" ns. "+cal);
long start2 = System.nanoTime();
long now = 0;
for(int i=0;i<runs;i++)
now = System.currentTimeMillis();
long time2 = System.nanoTime() - start2;
System.out.println("System.currentTimeMillis() took on average "+time2/runs+" ns. "+now);
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.
- uses more memory and less CPU
- uses less memory and more CPU
You have to decide what you want to give for the operation. What is the bottleneck in your application.
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.
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 of 23:59:59.875
and the second method is called with a time of 00: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.
- uses less memory and less CPU
- uses more memory and more CPU
The garbage collector is free to collect the Calendar instance immediately after the last use of a reference to it.
精彩评论